第二个 JFrame 中的组件未显示
我想通过按下 JFrame 中的按钮来启动另一个 JFrame.但是,如果我按下按钮,它会显示 JFrame,但不会显示其中的按钮和滑块.
i want to start another JFrame from pressing a button in a JFrame. But if I press the Button it shows the JFrame but not the Buttons and Sliders in it.
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);
}
}
第二个具有完全相同的 costructor.sliders 和按钮不是静态的.在按钮应该出现的地方,屏幕是黑色的.
The second has quite the same costructor.sliders and buttons are not static. At the places where Buttons should appear the screen is black.
希望你能帮助我:)
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
成为你调用的最后一件事...
Make setVisible
the last thing you call...
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()
来鼓励容器在添加新组件时更新其布局
Also, use revalidate()
and repaint()
to encourage the container to update it's layout when adding new components
建议:
- 确保您的 UI 在 EDT 的上下文中启动,请参阅 初始线程了解更多详情
- 避免直接从
JFrame
等顶级容器扩展,而是考虑使用JPanel
作为基础容器.这个免费的用户界面可以让您使用更广泛的用例,并防止您陷入困境(因为您无法将框架添加到其他框架) - 使用多个 JFrame,好/坏做法?一个>
- Make sure your UI is started within the context of the EDT, see Initial Threads for more details
- Avoid extending directly from top level containers like
JFrame
and instead consider using aJPanel
as you base container. This free's up you UI to a wider range of use-cases and prevents you from getting locked in (as you can't add frames to other frames) - The Use of Multiple JFrames, Good/Bad Practice?
更新
你有两个直接的问题
Clicker
从JFrame
扩展而来,但是您正试图将其添加到另一个容器中,这在 Swing 中是不可能的并且会导致异常,但是...- 您正在使用
while (true)
循环阻塞事件调度线程,这意味着 Swing 无法处理任何新事件,包括repaint
事件
Clicker
extends from aJFrame
, but you are trying to add it to another container, this is not possible in Swing and will cause an exception, however...- You are blocking the Event Dispatching Thread with your
while (true)
loop, meaning that Swing is unable to process any new events, includingrepaint
events
例如...
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 组件,它带来了许多其他问题,但我们没有相应的代码,因此无法评论.
Now, Click
looks like it's UI component which brings up a bunch of other problems, but we don't have the code for that so it's impossible to comment.
直接的解决方案可能是使用:
The immediate solutions might be to use a:
SwingWorker
,请参阅 工作线程和 SwingWorker 了解更多详情
SwingWorker
, see Worker Threads and SwingWorker for more details
Swing Timer
,参见 如何使用摆动计时器了解更多详情
Swing Timer
, see How to use Swing Timers for more details
要记住的事情
- Swing(与大多数 UI 框架一样)是单线程的,任何阻塞该线程的事物(例如永无止境的循环)都会阻止它处理新事件,包括绘制事件,这会使您的应用看起来像是挂起",因为它有
- Swing 不是线程安全的.与 UI 的所有交互都必须在事件调度线程的上下文中进行.
SwingWorker
和 SwingTimer
都提供了安全更新 UI 的能力.
- Swing (like most UI frameworks) is single threaded, anything which blocks this thread (like never ending loops), will prevent it from processing new events, including paint events, which will make your application look like it's "hung", because it has
- Swing is NOT thread safe. All interactions with the UI MUST be made from within the context of the Event Dispatching Thread. Both
SwingWorker
and SwingTimer
provide the capability to update the UI safely.
相关文章