web-dev-qa-db-ja.com

サブクラスからawtフレームメソッドを呼び出す

この質問は、フレーム、Javaおよび Processing についてです。

この質問はかなり複雑に聞こえますが、実際はそうではありません。私はこれをシンプルな最小値に保つようにします。私は迷路ゲームで小さなボールを作成して、物理学とレンダリングに頭を悩ませています。今までは良い経験でしたが、レンガの壁に少しぶつかりました。
私が決定した一般的なレイアウトは、AWTフレーム内にPAppletを含み、フレームを閉じることでした。これは、一度に1つのパプレットのみを使用するように言われたためです。

PAppletは、レンダリングライブラリである ProcessingAppletクラスです。

ここにはメインを含む3つのクラスがあります

public class Menu extends PApplet
{
//images and buttons 
PImage background, playbtn1, playbtn2, hsbtn1, hsbtn2, abbtn1, abbtn2, exbtn1,     exbtn2;
FBox pBtn, hBtn, eBtn;

FWorld menu;

//simple constructor
public Menu()
{

}

public void setup()
{
    size(600, 400);
    smooth();
    Fisica.init(this);
    menu = new FWorld();

    //loading and placing images
    background = loadImage("MenuAlt.jpg");
    System.out.println(background);
    playbtn1 = loadImage("play1.gif");
    playbtn2 = loadImage("play2.gif");
    hsbtn1 = loadImage("high1.gif");
    hsbtn2 = loadImage("high2.gif");
    exbtn1 = loadImage("exit1.gif");
    exbtn2 = loadImage("exit2.gif");

    //loading and placing buttons
    pBtn = new FBox(120, 150);
    pBtn.setPosition(135, 215);
    pBtn.setDrawable(false);
    hBtn = new FBox(120, 150);
    hBtn.setPosition(295, 215);
    hBtn.setDrawable(false);
    eBtn = new FBox(120, 150);
    eBtn.setPosition(455, 215);
    eBtn.setDrawable(false);

    //add item to world
    menu.add(pBtn);
    menu.add(hBtn);
    menu.add(eBtn);
}

public void draw()
{
    image(background, 0, 0);
    image(playbtn1, 80, 140);
    image(hsbtn1, 237, 135);
    image(exbtn1, 400, 140);

    mouseOver();
    menu.draw();
}

//close this frame an open a new level, high score or exit
//depending on what the use clicks
public void mousePressed()
{
    FBody pressed = menu.getBody(mouseX, mouseY);
    if (pressed == pBtn)
    {
        System.out.println("play game");
        this.getParent().getParent().getParent().getParent().setVisible(false);

        ExampleFrame x = new ExampleFrame(new Level("level1.txt"));
        x.setLocation(this.getParent().getParent().getParent().getParent().getLocation());
    }
    if (pressed == hBtn)
    {
        System.out.println("high scores");
        this.getParent().getParent().getParent().getParent().setVisible(false);

        /* these are just for finding the parent
 System.out.println(this.getName());
 System.out.println(this.getParent().getName());
 System.out.println(this.getParent().getParent().getName());
 System.out.println(this.getParent().getParent().getParent().getName());
 System.out.println(this.getParent().getParent().getParent().getParent().getName());
         */
        ExampleFrame x = new ExampleFrame(new HighScores()); //for testing, you can change this to new menu()
        x.setLocation(this.getParent().getParent().getParent().getParent().getLocation());
    }
    if (pressed == eBtn)
    {
        System.out.println("exit");
        System.exit(0);
    }
}

exampleFrameクラス

public class ExampleFrame extends JFrame
{
    PApplet app;

    public ExampleFrame(PApplet emApp)
    {
        super("Ball Maze Game");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocation(200, 200);

        app = emApp;
        setSize(615,438);
        setVisible(true);

        setLayout(new BorderLayout());

        add(app, BorderLayout.CENTER);
        app.init();
    }
}

メイン

public class Main
{
    public static void main(String[] args) 
    {
        ExampleFrame x = new ExampleFrame(new Menu());
    }
}

MousePressed == ebtnがフレーム内のすべてのものであるときに発生する必要があることは削除され、ハイスコア画面がロードされます。ハイスコ​​アはメニューとほとんど同じです。ここには十分な数があるので、コードを投稿する必要はありません。

2番目のクラスは、フレームとして機能し、PAppletを保持するクラスです

結論として、PAppletからFrameメソッドを呼び出す方法、またはすべてのPAppletsコンテンツを削除して別のPAppletをロードする別の方法を誰かが知っていますか?

37
OVERTONE

答えるためにPAppletからFrameメソッドを呼び出す方法は?、コードスニペットを最小限に変更しました。この変更されたバージョンでは、ユーザーがマウスボタンをクリックすると、_System.out_が発生します。

これで、Frameオブジェクトにアクセスする方法が2つあります。ただし、その前に、次の2つの点を述べておきます。

  • new ExampleFrame(new Menu());のようなPAppletを作成し、JFrameにこのadd(app, BorderLayout.CENTER);のように追加すると、ウィンドウ/パネルの複雑な階層が作成されます。

これのように:

_javax.swing.JPanel
    javax.swing.JLayeredPane
        javax.swing.JRootPane
            test.ExampleFrame
_
  • PAppletは、フレームオブジェクトを設定およびアクセスするためのパブリックフィールドを提供します。そして驚くべきことに、それはframe :)と呼ばれています。 app.init();を呼び出す前に設定できます

>>コード

**コード内のコメントをチェックしてください**

Modified ExampleFrame.Java

_import Java.awt.BorderLayout;    
import javax.swing.JFrame;    
import processing.core.PApplet;

public class ExampleFrame extends JFrame
{
    private static final long serialVersionUID = 4792534036194728580L;
    PApplet app;

    public ExampleFrame(PApplet emApp)
    {
        super("Ball Maze Game");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocation(200, 200);

        app = emApp;
        setSize(615,438);
        setVisible(true);

        setLayout(new BorderLayout());

        add(app, BorderLayout.CENTER);

        // Setting my frame object
        app.frame = this;       
        app.init();
    }

    // Sample Method
    public void sampleMethod(String msg)
    {
        System.out.println("I think '"+ msg +"' called me !!");
    }
}
_

Modified Menu.Java

_import Java.awt.Container;

import processing.core.PApplet;
import processing.core.PImage;

public class Menu extends PApplet
{
    private static final long serialVersionUID = -6557167654705489372L;

    PImage background;
    static String tab = "";

    //simple constructor
    public Menu()
    {

    }

    public void setup()
    {
        size(600, 400);
        smooth();

        background = loadImage("C:/temp/background.jpg");
    }

    public void draw()
    {
        image(background, 0, 0);
    }

    public void mousePressed()
    {
        Container p = getParent();
        tab = "";

        // FIRST WAY OF ACCESSING PARENT FRAME
        while(p != null)
        {
            //printParentTree(p);
            if(p instanceof ExampleFrame)
            {
                ExampleFrame myframe = (ExampleFrame)p;
                myframe.sampleMethod("First Way");
                break;
            }
            p = p.getParent();
        }

        // SECOND WAY OF ACCESSING PARENT FRAME     
        if(frame != null && (frame instanceof ExampleFrame))
        {
            ExampleFrame myframe = (ExampleFrame)p;
            myframe.sampleMethod("Second Way");
        }
    }

    void printParentTree(Container p) 
    {
        System.out.println(tab+p.getClass().getName());
        tab +='\t';
    }
}
_

public void mousePressed()メソッドをチェックアウトします。

完全を期すために、Main.Javaも含めています。

_public class Main {
    public static void main(String[] args){
        new ExampleFrame(new Menu());
    }
}
_

ここで答えますすべてのPAppletsのコンテンツを削除し、別のPAppletをロードします

まあ私はそれをテストしていません。ただし、JPanelJAppletに追加して、すべての描画を実行できます。つまり、子コントロールを作成します。再描画したい場合は、JPanel.removeAll()を呼び出します。 javadocによると:

このコンテナからすべてのコンポーネントを削除します。このメソッドは、removeLayoutComponentメソッドを介してこのコンテナーのレイアウトからコンポーネントを削除するようにレイアウトマネージャーにも通知します。

この後、repaintJPanelを呼び出します。それを試してみてください、それはうまくいくかもしれません:)。

9
Favonius

MousePressed == ebtnがフレーム内のすべてのものであるときに発生する必要があることは削除され、ハイスコア画面がロードされます

デモ。ネストされたCardLayoutの下に、ActionListenerではなくMouseListenerを追加します。両方のマウスに反応しますおよびキーボード入力。

同じ画面スペースに複数のGUI要素を含める方法は他にも多数あります。頭上から、JTabbedPaneJSplitPaneJDesktopPane/JInternalFrame、ハイスコアをJDialogまたはJOptionPane ..

スクリーンショット

Game viewHigh Scores view

CardLayoutDemo.Java

import Java.awt.*;
import Java.awt.event.*;
import javax.swing.*;

class CardLayoutDemo {

    public static void main(String[] args) {

        Runnable r = new Runnable () {
            public void run() {
                final JRadioButton game = new JRadioButton("Game", true);
                JRadioButton highScores = new JRadioButton("High Scores");

                ButtonGroup bg = new ButtonGroup();
                bg.add( game );
                bg.add( highScores );

                JPanel buttons = new JPanel(new 
                    FlowLayout(FlowLayout.CENTER, 5, 5));
                buttons.add( game );
                buttons.add( highScores );

                JPanel gui = new JPanel(new BorderLayout(5,5));
                gui.add(buttons, BorderLayout.SOUTH);

                final CardLayout cl = new CardLayout();
                final JPanel cards = new JPanel(cl);
                gui.add(cards);
                cards.add(new JLabel("Level 1"), "game");
                cards.add(new JLabel("High Scores"), "scores");

                ActionListener al = new ActionListener(){
                    public void actionPerformed(ActionEvent ae) {
                        if (game.isSelected()) {
                            cl.show(cards, "game");
                        } else {
                            cl.show(cards, "scores");
                        }
                    }
                };
                game.addActionListener(al);
                highScores.addActionListener(al);

                JOptionPane.showMessageDialog(null, gui);
            }
        };
        SwingUtilities.invokeLater(r);
    }
}
19
Andrew Thompson