Java,swing,wait(),notify()的问题

发布于 2025-02-06 17:44:20 字数 3535 浏览 2 评论 0原文

我是Java的新手,我尝试制作一个简单的基于转弯的游戏只是为了获得一些经验。尽管我做了很多Google的研究,但我遇到了一个无法独自解决的问题……也许我无法解决它,因为我的理解不够好。

问题是我不知道如何为玩家进行程序。我的意思是,我想使一些jbuttons活跃起来,直到按下其中一个,然后为另一个球员做同样的事情。由于程序很安静,因此我删除了与问题无关的80%的代码,并在下面发布了其余的代码。

该代码分为课程,由于问题的同谋,我想以这种方式保持这种方式(剩余的80%代码)。为了更好地查看程序的操作,我每次激活时都会制作按钮以更改颜色。不幸的计划一旦达到notify()方法就停止工作。

谁能帮忙?先感谢您。

测试器:

package grafika;

import javax.swing.SwingUtilities;


public class OknoTester {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                Okno main = new Okno();
            }
            
            // ctr + spacja - podpowiedzi w Eclipsie
        });

    }

}

主类

 package grafika;

import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JSplitPane;


public class Okno {
    private JFrame frame;
            
    public Okno()
    {
        initialize();
    }

    
    private void initialize()
    {
        // NEW WINDOW
        frame = new JFrame();
        frame.setTitle("Gra w statki");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setSize(new Dimension(600,100));
        frame.setLocationRelativeTo(null);
        frame.setResizable(false);
        frame.setVisible(true);

        
        // DIVIDE WINDOW
        JSplitPane splitPaneH = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT );
        frame.getContentPane().add(splitPaneH);
        splitPaneH.setDividerSize(0);
        
        
        // INITIALIZATION OF SITES
        Komputer left = new Komputer();
        Komputer right = new Komputer();
        

        // SHOWPANELS
        splitPaneH.setLeftComponent(left.Pokaz());
        splitPaneH.setRightComponent(right.Pokaz());
        splitPaneH.setResizeWeight(0.5);
        splitPaneH.setEnabled(false);
        
        // ALLOW TO USE ONE OF LEFT OR RIGHT SET OF BUTTONS
        while(true)
        {
        left.CzytajRuch();
        right.CzytajRuch();
        }
        
        
    }

}

带按钮的类

package grafika;

import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;

public class Komputer implements ActionListener{

    private JButton b1 = new JButton("1");
    private JButton b2 = new JButton("2");
    private JPanel panel = new JPanel();
    private Boolean aktywny = false;
    
    
    public void CzytajRuch()
    {
        aktywny = true;
        try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    }

    public JPanel Pokaz()
    {
        return panel;
    }
    

    public Komputer() {
        
        GridLayout gl = new GridLayout(1,2);
        panel.setLayout(gl);
        panel.add(b1);
        b1.addActionListener(this);
        b2.addActionListener(this);
        panel.add(b2);

    }


    public void actionPerformed(ActionEvent ae) {
        if(aktywny == true)
        {
        JButton pb = (JButton) ae.getSource();
        if (pb == b1)
            b1.setBackground(new Color((int)(Math.random() * 0x1000000)));
        if (pb == b2)
            b2.setBackground(new Color((int)(Math.random() * 0x1000000)));
        aktywny = false;
        notify();
        }
    }
    

}
 

感谢您的时间阅读此书。我会批准任何帮助。

I am quiet new to Java and I try to make a simple turn-based game just to gain some experience. I have encounter a problem which I cannot solve on my own, despite I did quiet a lot of google research... Probably I cannot solve it because I don't understand it well enough.

The problem is I don't know how to make a program making turns for player. I mean I would like to make a few Jbuttons active till one of them is pressed and then do the same for another player. Since program is quiet complicated, I deleted 80% of code which is unrelated to problem and I post the rest of it below.

The code is divided into classes and I would like to keep it this way due to complicity of a problem (remaining 80% of code). In order to see better what programs do, I made buttons to change colours each time when activated. Unfortunatelly program stops working as soon as it hits notify() method.

Can anyone help? Thank you in advance.

Tester:

package grafika;

import javax.swing.SwingUtilities;


public class OknoTester {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                Okno main = new Okno();
            }
            
            // ctr + spacja - podpowiedzi w Eclipsie
        });

    }

}

Main class

 package grafika;

import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JSplitPane;


public class Okno {
    private JFrame frame;
            
    public Okno()
    {
        initialize();
    }

    
    private void initialize()
    {
        // NEW WINDOW
        frame = new JFrame();
        frame.setTitle("Gra w statki");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setSize(new Dimension(600,100));
        frame.setLocationRelativeTo(null);
        frame.setResizable(false);
        frame.setVisible(true);

        
        // DIVIDE WINDOW
        JSplitPane splitPaneH = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT );
        frame.getContentPane().add(splitPaneH);
        splitPaneH.setDividerSize(0);
        
        
        // INITIALIZATION OF SITES
        Komputer left = new Komputer();
        Komputer right = new Komputer();
        

        // SHOWPANELS
        splitPaneH.setLeftComponent(left.Pokaz());
        splitPaneH.setRightComponent(right.Pokaz());
        splitPaneH.setResizeWeight(0.5);
        splitPaneH.setEnabled(false);
        
        // ALLOW TO USE ONE OF LEFT OR RIGHT SET OF BUTTONS
        while(true)
        {
        left.CzytajRuch();
        right.CzytajRuch();
        }
        
        
    }

}

Class with buttons

package grafika;

import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;

public class Komputer implements ActionListener{

    private JButton b1 = new JButton("1");
    private JButton b2 = new JButton("2");
    private JPanel panel = new JPanel();
    private Boolean aktywny = false;
    
    
    public void CzytajRuch()
    {
        aktywny = true;
        try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    }

    public JPanel Pokaz()
    {
        return panel;
    }
    

    public Komputer() {
        
        GridLayout gl = new GridLayout(1,2);
        panel.setLayout(gl);
        panel.add(b1);
        b1.addActionListener(this);
        b2.addActionListener(this);
        panel.add(b2);

    }


    public void actionPerformed(ActionEvent ae) {
        if(aktywny == true)
        {
        JButton pb = (JButton) ae.getSource();
        if (pb == b1)
            b1.setBackground(new Color((int)(Math.random() * 0x1000000)));
        if (pb == b2)
            b2.setBackground(new Color((int)(Math.random() * 0x1000000)));
        aktywny = false;
        notify();
        }
    }
    

}
 

Thank you for your time reading this. I would apprieciate any help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

完美的未来在梦里 2025-02-13 17:44:20

秋千是单线螺纹。这意味着您不能在派遣线程的事件上执行长时间的运行或阻止操作。

如果您尝试在EDT的上下文中使用等待,它不仅会阻止EDT并防止处理过任何进一步的更新或事件,而且您将永远无法使用Notify notify < /code>(从EDT内部)唤醒它。

等待notify是从不同的线程上下文(不是在同一线程上下文中)使用的,

请参见 Swing中的并发有关更多详细信息。

您需要做的是监视某种“代币”。只有拥有“代币”的球员才能做任何事情。

您可以通过某种“控制器”来将其提炼为简单的标志。每次玩家做某事时,控制器都会检查播放器当前是否处于活动状态时,处理动作,然后将活动播放器切换到其他玩家,例如...

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public final class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new MainPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    enum Player {
        LEFT, RIGHT;
    }

    public class MainPane extends JPanel {

        private Player activePlayer = Player.LEFT;
        private ControlPane leftControlPane;
        private ControlPane rightControlPane;

        private JTextArea logTextArea;

        public MainPane() {
            ControlPane.Observer observer = new ControlPane.Observer() {
                @Override
                public void playerDidPerformAction(ControlPane source, Player player) {
                    if (player != getActivePlayer()) {
                        logTextArea.append((player == Player.LEFT ? "Player 1" : "Player 2") + " tried to perform an illegal action\n");
                    } else {

                        logTextArea.append((player == Player.LEFT ? "Player 1" : "Player 2") + " did perform action\n");
                        switch (player) {
                            case LEFT:
                                activePlayer = Player.RIGHT;
                                break;
                            case RIGHT:
                                activePlayer = Player.LEFT;
                                break;
                        }
                        activePlayerDidChange();
                    }
                }
            };
            leftControlPane = new ControlPane(Player.LEFT, observer);
            rightControlPane = new ControlPane(Player.RIGHT, observer);

            logTextArea = new JTextArea(20, 20);

            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();

            gbc.gridheight = GridBagConstraints.REMAINDER;
            gbc.weightx = 1;
            gbc.weighty = 1;
            gbc.fill = gbc.BOTH;
            add(leftControlPane, gbc);

            gbc.weightx = 0;
            gbc.weighty = 0;
            add(new JScrollPane(logTextArea), gbc);

            gbc.weightx = 1;
            gbc.weighty = 1;
            add(rightControlPane, gbc);

            activePlayerDidChange();
        }

        public Player getActivePlayer() {
            return activePlayer;
        }

        protected void activePlayerDidChange() {
            switch (getActivePlayer()) {
                case LEFT:
                    rightControlPane.setActive(false);
                    leftControlPane.setActive(true);
                    break;
                case RIGHT:
                    rightControlPane.setActive(true);
                    leftControlPane.setActive(false);
                    break;
            }
        }

    }

    public class ControlPane extends JPanel {
        public interface Observer {
            public void playerDidPerformAction(ControlPane source, Player player);
        }

        private Player player;
        private JButton actionButton;
        private Observer observer;

        public ControlPane(Player player, Observer observer) {
            this.player = player;
            this.observer = observer;
            actionButton = new JButton("Do stuff!");

            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            gbc.insets = new Insets(8, 8, 8, 8);

            add(new JLabel(player == Player.LEFT ? "Player 1" : "Player 2"), gbc);

            gbc.weightx = 1;
            gbc.weighty = 1;
            add(actionButton, gbc);

            actionButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    observer.playerDidPerformAction(ControlPane.this, player);
                }
            });
        }

        public void setActive(boolean active) {
            actionButton.setEnabled(active);
        }

    }
}

Swing is single threaded. This means you can't perform long running or blocking operations on the Event Dispatching Thread.

If you try and use wait within the context of the EDT, not only will it block the EDT and prevent any further updates or events from been processed, you will never be able to use notify (from within the EDT) to wake it.

wait and notify are meant to be used from different thread contexts (not from within the same thread context)

See Concurrency in Swing for some more details.

What you need to do, is monitor some kind of "token". Only the player with who holds the "token" can do anything.

You can distill this down to a simple flag is maintained by some kind "controller". Each time a player does something, the controller checks to see if the player is currently active or not, processes the action and the switches the active player to a different player, for example...

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public final class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new MainPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    enum Player {
        LEFT, RIGHT;
    }

    public class MainPane extends JPanel {

        private Player activePlayer = Player.LEFT;
        private ControlPane leftControlPane;
        private ControlPane rightControlPane;

        private JTextArea logTextArea;

        public MainPane() {
            ControlPane.Observer observer = new ControlPane.Observer() {
                @Override
                public void playerDidPerformAction(ControlPane source, Player player) {
                    if (player != getActivePlayer()) {
                        logTextArea.append((player == Player.LEFT ? "Player 1" : "Player 2") + " tried to perform an illegal action\n");
                    } else {

                        logTextArea.append((player == Player.LEFT ? "Player 1" : "Player 2") + " did perform action\n");
                        switch (player) {
                            case LEFT:
                                activePlayer = Player.RIGHT;
                                break;
                            case RIGHT:
                                activePlayer = Player.LEFT;
                                break;
                        }
                        activePlayerDidChange();
                    }
                }
            };
            leftControlPane = new ControlPane(Player.LEFT, observer);
            rightControlPane = new ControlPane(Player.RIGHT, observer);

            logTextArea = new JTextArea(20, 20);

            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();

            gbc.gridheight = GridBagConstraints.REMAINDER;
            gbc.weightx = 1;
            gbc.weighty = 1;
            gbc.fill = gbc.BOTH;
            add(leftControlPane, gbc);

            gbc.weightx = 0;
            gbc.weighty = 0;
            add(new JScrollPane(logTextArea), gbc);

            gbc.weightx = 1;
            gbc.weighty = 1;
            add(rightControlPane, gbc);

            activePlayerDidChange();
        }

        public Player getActivePlayer() {
            return activePlayer;
        }

        protected void activePlayerDidChange() {
            switch (getActivePlayer()) {
                case LEFT:
                    rightControlPane.setActive(false);
                    leftControlPane.setActive(true);
                    break;
                case RIGHT:
                    rightControlPane.setActive(true);
                    leftControlPane.setActive(false);
                    break;
            }
        }

    }

    public class ControlPane extends JPanel {
        public interface Observer {
            public void playerDidPerformAction(ControlPane source, Player player);
        }

        private Player player;
        private JButton actionButton;
        private Observer observer;

        public ControlPane(Player player, Observer observer) {
            this.player = player;
            this.observer = observer;
            actionButton = new JButton("Do stuff!");

            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            gbc.insets = new Insets(8, 8, 8, 8);

            add(new JLabel(player == Player.LEFT ? "Player 1" : "Player 2"), gbc);

            gbc.weightx = 1;
            gbc.weighty = 1;
            add(actionButton, gbc);

            actionButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    observer.playerDidPerformAction(ControlPane.this, player);
                }
            });
        }

        public void setActive(boolean active) {
            actionButton.setEnabled(active);
        }

    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文