[英]Problem with Java, Swing, wait(), notify()
我是 Java 的新手,我嘗試制作一個簡單的回合制游戲來獲得一些經驗。 我遇到了一個我自己無法解決的問題,盡管我做了很多谷歌研究......可能我無法解決它是因為我對它的理解不夠深入。
問題是我不知道如何為玩家制作輪流程序。 我的意思是我想讓幾個 Jbutton 處於活動狀態,直到按下其中一個按鈕,然后對另一個玩家執行相同的操作。 由於程序非常復雜,我刪除了 80% 與問題無關的代碼,並將它的 rest 貼在下面。
代碼分為類,由於問題的復雜性(剩余 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
});
}
}
主 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 帶按鍵
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();
}
}
}
感謝您花時間閱讀本文。 我會感謝任何幫助。
Swing 是單線程的。 這意味着您不能在事件調度線程上執行長時間運行或阻塞操作。
如果您嘗試在 EDT 的上下文中使用wait
,它不僅會阻止 EDT 並阻止處理任何進一步的更新或事件,您將永遠無法使用notify
(從 EDT 中)喚醒它。
wait
和notify
旨在從不同的線程上下文中使用(而不是在同一線程上下文中)
有關更多詳細信息,請參閱Swing中的並發。
您需要做的是監視某種“令牌”。 只有持有“令牌”的玩家才能做任何事情。
您可以將其提煉為一個簡單的標志,由某種“控制器”維護。 每次玩家做某事時,controller 都會檢查玩家當前是否處於活動狀態,處理該動作並將活動玩家切換到其他玩家,例如......
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);
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.