我现在在使用 JButton
时遇到问题。
我的 JButton
不会添加到 JFrame
或 JPanel
中,并且它似乎禁用了 paintComponent()
正在运行。
这是我的 JPanel 类:
public class BLANKScreen extends JPanel implements Runnable {
Thread thread = new Thread(this);
public boolean running = false;
public static ImageIcon greenButton = new ImageIcon("resources/menubuttons/GreenButton.png");
public static JButton mainMenuPlayButton = new JButton("Play!", greenButton);
private int fps;
static BLANKWindow w;
public int scene = 0;
public void run() {
long lastFrame = System.currentTimeMillis();
int frames = 0;
running = true;
scene = 0;
while (running) {
if (scene == 0) {
addMainMenuButtonsOptions();
} else if (scene == 1) {
}
repaint();
frames++;
if (System.currentTimeMillis() - 1000 >= lastFrame) {
fps = frames;
frames = 0;
lastFrame = System.currentTimeMillis();
}
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.exit(0);
}
public BLANKScreen (BLANKWindow w) {
this.w = w;
this.w.addKeyListener(new KeyHandler(this));
this.w.addMouseListener(new MouseHandler(this));
thread.start();
}
public class KeyTyped {
public void keyESC() {
running = false;
}
public void keySpace() {
if (scene == 0) {
scene = 1;
} else if (scene == 1) {
scene = 0;
}
}
}
public class MouseClicked { }
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.clearRect(0, 0, this.w.getWidth(), this.w.getHeight());
if (scene == 0) {
int nameLength = g.getFontMetrics().stringWidth("BLANK!");
g.drawString("BLANK!", w.getWidth() / 2 - nameLength / 2, w.getHeight() / 4);
}
}
public void addMainMenuButtonsOptions() {
mainMenuPlayButton.setActionCommand("/mainMenuPlayButton");
mainMenuPlayButton.addActionListener(new ActionHandler());
this.add(mainMenuPlayButton);
System.out.println("ThingHappend");
}
}
当我说 w.add(mainMenuPlayButton);
时,this.add(mainMenuPlayButton);
也不起作用。
这是我的 JFrame 类:
public class BLANKWindow extends JFrame {
public static void main(String[] args) {
new BLANKWindow();
}
public BLANKWindow() {
new JFrame();
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
int screenHeight = screenSize.height;
int screenWidth = screenSize.width;
this.setSize(screenWidth, screenHeight);
this.setTitle("BLANK");
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setResizable(true);
this.setExtendedState(MAXIMIZED_BOTH);
this.setVisible(true);
BLANKScreen dbs = new BLANKScreen(this);
this.add(dbs);
}
}
出于某种原因,JButton
和 paintCompenent()
都没有决定加载?
最佳答案
基本上,在核心,您违反了 Swing API 的线程,并且似乎缺乏对 Swing 基本工作原理的了解...欢迎来到危险区域...
Swing 是单线程的并且不是线程安全的。这意味着您应该阻止 EDT,但也不应该与 EDT 外部的任何 UI 组件交互或修改任何 UI 组件
你需要改变你的方法。
Swing 已经有一个事件队列、一个用于处理这些事件的线程、事件调度线程,并使用被动绘制算法来更新 UI(和布局管理器)。
您需要在这些限制范围内工作才能使一切顺利。
您应该从“菜单面板”和“游戏面板”之类的东西开始,而不是尝试在 BLANKScreen
类中切换状态。
“菜单面板”将向用户显示菜单选项,“游戏面板”将显示游戏,它将具有实际游戏的游戏循环和绘画逻辑。
现在,你“可以”让它们一起工作,但我认为你需要首先将它们分开......这只会让问题变得复杂......
然后您可以使用 CardLayout
在它们之间切换。这将使更改可见状态变得更容易。
另请查看:
已更新...
面向对象编程的第一条规则——职责分离。一个对象负责它的工作,并且只负责它的工作。如果您发现您的对象正在尝试执行更多操作(例如更新游戏帧并显示菜单),那么您的想法就错误了(尤其是在这种情况下)。
您需要将菜单与游戏分开。游戏有更新机制,菜单不管,不需要,是核心框架更新的。
游戏有自己的用户交互,菜单也有,但它们彼此有不同的含义(鼠标单击菜单会执行某些操作,但在游戏中会执行其他操作),因此它们应该分开。 ..
菜单和游戏可能根本不关心彼此,因此您可以使用某种 Controller ,它控制两者之间的状态并促进通信
这是一个粗略的示例,我通常会花更多时间构建更好的 Controller 和模型,但这旨在演示概念的要点,而不是提供完全的、开箱即用的运行解决方案...
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestGameMenu {
public static void main(String[] args) {
new TestGameMenu();
}
public TestGameMenu() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new MainView());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MainView extends JPanel {
private MenuPane menuPane;
private GamePane gamePane;
public MainView() {
setLayout(new CardLayout());
menuPane = new MenuPane();
gamePane = new GamePane();
add(menuPane, "menu");
add(gamePane, "game");
menuPane.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if ("play".equalsIgnoreCase(e.getActionCommand())) {
((CardLayout) getLayout()).show(MainView.this, "game");
gamePane.resume();
}
}
});
}
}
public class MenuPane extends JPanel {
private JButton playGame;
public MenuPane() {
setLayout(new GridBagLayout());
playGame = new JButton("Play My Awesome Game!");
playGame.setActionCommand("play");
add(playGame);
}
public void addActionListener(ActionListener listener) {
playGame.addActionListener(listener);
}
public void removeActionListener(ActionListener listener) {
playGame.removeActionListener(listener);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
public class GamePane extends JPanel {
private Point p;
private int xDelta;
private int yDelta;
private volatile boolean running = true;
private volatile boolean paused = true;
private ReentrantLock lckPause;
private Condition conPause;
public GamePane() {
p = new Point(100, 100);
do {
xDelta = (int)((Math.random() * 10) - 5);
} while (xDelta == 0);
do {
yDelta = (int)((Math.random() * 10) - 5);
} while (yDelta == 0);
lckPause = new ReentrantLock();
conPause = lckPause.newCondition();
Thread t = new Thread(new Runnable() {
@Override
public void run() {
while (running) {
while (paused) {
lckPause.lock();
try {
conPause.await();
} catch (InterruptedException ex) {
} finally {
lckPause.unlock();
}
}
p.x += xDelta;
p.y += yDelta;
if (p.x < 0) {
p.x = 0;
xDelta *= -1;
} else if (p.x > getWidth()) {
p.x = getWidth();
xDelta *= -1;
}
if (p.y < 0) {
p.y = 0;
yDelta *= -1;
} else if (p.y > getHeight()) {
p.y = getHeight();
yDelta *= -1;
}
repaint();
if (running && !paused) {
try {
Thread.sleep(40);
} catch (InterruptedException ex) {
}
}
}
}
});
t.start();
}
public void pause() {
if (!paused && running) {
lckPause.lock();
try {
paused = true;
} finally {
lckPause.unlock();
}
}
}
public void resume() {
if (paused && running) {
lckPause.lock();
try {
paused = false;
conPause.signalAll();
} finally {
lckPause.unlock();
}
}
}
public void stop() {
if (running) {
lckPause.lock();
try {
paused = false;
running = false;
conPause.signalAll();
} finally {
lckPause.unlock();
}
}
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.RED);
g2d.fillOval(p.x - 5, p.y - 5, 10, 10);
g2d.dispose();
}
}
}
关于java - 将 JButton 添加到 Window 时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25901014/