我想通过按下JFrame中的按钮来启动另一个JFrame。但如果我按下按钮它会显示JFrame但不会显示其中的按钮和滑块。
public class MainMenu extends JFrame {
private JFrame klick;
private static final long serialVersionUID = 9002;
public static void main(String[] args) {
new MainMenu();
}
public MainMenu() {
buildGUI1();
}
public void buildGUI1() throws NullPointerException {
setTitle("Hauptmenü");
setSize(800, 480);
setLayout(new GridLayout());
setAlwaysOnTop(false);
setLocation((Toolkit.getDefaultToolkit().getScreenSize().width)/4, (Toolkit.getDefaultToolkit().getScreenSize().height)/4);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
setVisible(true);
final JButton startclickbt = new JButton("Start Clicker");
startclickbt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dispose();
if(klick == null ) {
klick =new Clicker();
add(klick);
}
}
});
add(startclickbt);
}
}
第二个具有完全相同的构造函数。滑块和按钮不是静态的。在按钮应该出现的地方,屏幕是黑色的。
希望你能帮助我:)
编辑:public class Clicker extends JFrame {
private static final long serialVersionUID = 9001;
protected JPanel panel;
static Click j = null;
protected JSlider jsl;
protected JTextField tf;
static final int CPS_MIN= 0;
static final int CPS_MAX= 100;
static final int CPS_INIT= 25;
private int amount;
private boolean visible;
public int getDelay() {
return Math.abs(jsl.getValue()-100);
}
public int getAmount() {
return amount;
}
public boolean getVisible() {
return visible;
}
public void setOpen(boolean visible) {
this.visible=visible;
}
public Clicker(boolean visible) {
buildGUI(visible);
j = new Click(false).addPosition(new Point((Toolkit.getDefaultToolkit().getScreenSize().width)/2, (Toolkit.getDefaultToolkit().getScreenSize().height)/2)).addPosition(new Point(getLocation().x+1, getLocation().y+20));
while(true) {
j.runClicks(getDelay());
}
}
public Clicker() {
buildGUI(true);
j = new Click(false).addPosition(new Point((Toolkit.getDefaultToolkit().getScreenSize().width)/2, (Toolkit.getDefaultToolkit().getScreenSize().height)/2)).addPosition(new Point(getLocation().x+1, getLocation().y+20));
while(true) {
j.runClicks(getDelay());
}
}
public void buildGUI(boolean visible) {
setTitle("Clicker");
setSize(340, 200);
setLayout(new GridLayout());
setAlwaysOnTop(true);
setLocation(0, 0);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
setVisible(visible);
final JButton bt1 = new JButton("Schließen");
bt1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
final JButton bt2 = new JButton("Start ");
bt2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
j.setClick(true);
}
});
final JButton bt3 = new JButton("Stop ");
bt3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
j.setClick(false);
JOptionPane.showMessageDialog(null, "Klicken gestoppt. Klicks: " + j.getClickAmount());
j.setClickAmout(0);
}
});
final JButton bt4 = new JButton("StartAnzahl");
bt4.addActionListener(new ActionListener() {
private int amount;
public void actionPerformed(ActionEvent e) {
String wert = tf.getText();
try {
amount = Integer.parseInt(wert);
}catch(Exception ee) {
JOptionPane.showMessageDialog(null,"Das war keine Zahl oder mehr als ein Integer");
}
j.doClick(amount);
}
});
tf = new JTextField("Anzahl gewünschte Clicks max "+ Integer.MAX_VALUE, 10);
tf.setEditable(true);
jsl = new JSlider(JSlider.HORIZONTAL,CPS_MIN,CPS_MAX,CPS_INIT);
jsl.setMinorTickSpacing(5);
jsl.setMajorTickSpacing(10);
jsl.setPaintTicks(true);
jsl.setPaintLabels(true);
panel = new JPanel();
panel.addMouseMotionListener(new MouseMotionListener() {
@Override
public void mouseDragged(MouseEvent event) {
j.setClick(false);
}
@Override
public void mouseMoved(MouseEvent event) {
j.setClick(false);
}
});
panel.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_F1) {
j.setClick(true);
}
if(e.getKeyCode() == KeyEvent.VK_F2) {
j.setClick(false);
}
}
});
add(panel);
add(bt2);
add(bt3);
add(bt1);
add(bt4);
add(jsl);
add(tf);
pack();
}
}
让setVisible
成为你的最后一个…
public void buildGUI1() throws NullPointerException {
setTitle("Hauptmenü");
setSize(800, 480);
setLayout(new GridLayout());
setAlwaysOnTop(false);
setLocation((Toolkit.getDefaultToolkit().getScreenSize().width) / 4, (Toolkit.getDefaultToolkit().getScreenSize().height) / 4);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
final JButton startclickbt = new JButton("Start Clicker");
startclickbt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dispose();
if (klick == null) {
klick = new Clicker();
add(klick);
// Add this when you need to add/remove components
revalidate();
repaint();
}
}
});
add(startclickbt);
// Move to here
setVisible(true);
}
另外,使用revalidate()
和repaint()
来鼓励容器在添加新组件时更新其布局
建议:
- 确保你的UI是在EDT的上下文中启动的,更多细节请参见初始化线程 避免直接从顶级容器(如
- 使用多个jframe,好/坏的做法?
JFrame
)扩展,而是考虑使用JPanel
作为基础容器。这可以让你的UI更广泛的用例,并防止你被锁定(因为你不能添加帧到其他帧)你有两个紧迫的问题
-
Clicker
从JFrame
扩展,但您试图将其添加到另一个容器中,这在Swing中是不可能的,并且会导致异常,但是… - 你用
while (true)
循环阻塞了事件调度线程,这意味着Swing无法处理任何新的事件,包括repaint
事件
public Clicker(boolean visible) {
buildGUI(visible);
j = new Click(false).addPosition(new Point((Toolkit.getDefaultToolkit().getScreenSize().width) / 2, (Toolkit.getDefaultToolkit().getScreenSize().height) / 2)).addPosition(new Point(getLocation().x + 1, getLocation().y + 20));
// This is bad
while (true) {
j.runClicks(getDelay());
}
}
public Clicker() {
buildGUI(true);
j = new Click(false).addPosition(new Point((Toolkit.getDefaultToolkit().getScreenSize().width) / 2, (Toolkit.getDefaultToolkit().getScreenSize().height) / 2)).addPosition(new Point(getLocation().x + 1, getLocation().y + 20));
// This is bad
while (true) {
j.runClicks(getDelay());
}
}
现在,Click
看起来像它的UI组件带来了一堆其他的问题,但我们没有代码,所以它是不可能的注释。
直接的解决方案可能是使用:
SwingWorker
,参见Worker Threads和SwingWorker了解更多细节Swing
Timer
,参见如何使用Swing计时器了解更多细节- 普通旧
Thread
要记住的事情
- Swing(像大多数UI框架一样)是单线程的,任何阻塞这个线程的东西(像永无止境的循环),将阻止它处理新的事件,包括油漆事件,这将使你的应用程序看起来像"挂起",因为它有Swing不是线程安全的。所有与UI的交互都必须在事件调度线程的上下文中进行。
SwingWorker
和Swing Timer
都提供安全更新UI的功能。尝试在构造函数的末尾使用repaint()
或revalidate()
。并尝试在最后调用setVisible(true)
。