“切换场景"在Java Swing中 [英] "Switch Scenes" in Java Swing
问题描述
这不是问题.
我没有在互联网上找到任何有关它的信息,所以我尝试自己做,我有一个很好的主意,我想与以后搜索它的人分享.
I didn't find anything about it on the internet, so I tried to do it myself and I had a pretty good idea that I want to share for the people who search it in the future.
当您在Google上切换Java场景"时,它说:使用JavaFX切换场景",但是我不想使用JavaFX并继续使用Java Swing.
When you google "Switch scenes Java" it says: "Switch scenes using JavaFX", but I don't want to work with JavaFX and stay with Java Swing.
然后我有了一个绝妙的主意,下面将向您展示:(我不是专业的程序员,也不是其他任何人,我16岁,还是小学生,所以我的代码不会很完美)
Then I had that brilliant idea, which I want to show you in the following: (Im not a professional programmer or anything, Im 16 years old and a pupil, so my code won't be perfect)
这个想法是使用多个JFrame并设置相对于彼此的位置.然后将未运行的JFrame设置为visible(false)并对其进行dispose().
The idea is to use multiple JFrames and set the location relative to eachother. Then set the not running JFrame to visible(false) and dispose() it.
这是我写的代码:
- 为第一个JFrame和ActionListener创建类以在两个JFrame之间切换:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class mainTest {
public static JFrame frame1;
JLabel hello1;
JButton b1;
static Handler handler;
mainTest(){
frame1 = new JFrame();
frame1.setSize(900,600);
frame1.setResizable(false);
frame1.setTitle("Frame 1");
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame1.setLocationRelativeTo(GUI2.frame2);
frame1.setLayout(null);
frame1.setVisible(true);
handler = new Handler();
hello1 = new JLabel("Hello Frame 1");
hello1.setBounds(100,100,100,20);
frame1.add(hello1);
b1 = new JButton("Go to Frame 2");
b1.setBounds(100,300,200,50);
b1.addActionListener(handler);
frame1.add(b1);
}
public class Handler implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == b1) {
new GUI2();
frame1.setVisible(false);
frame1.dispose();
}if(e.getSource() == GUI2.b2) {
new mainTest();
GUI2.frame2.setVisible(false);
GUI2.frame2.dispose();
}
}
}
public static void main(String args[]) {
new mainTest();
}
}
- 为第二个JFrame创建类:
mport javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class GUI2 {
public static JFrame frame2;
public static JButton b2;
public JLabel hello2;
GUI2(){
frame2 = new JFrame();
frame2.setSize(900,600);
frame2.setResizable(false);
frame2.setTitle("Frame 2");
frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame2.setLocationRelativeTo(mainTest.frame1);
frame2.setLayout(null);
frame2.setVisible(true);
b2 = new JButton("Got to Frame 1");
b2.setBounds(100,300,200,50);
b2.addActionListener(mainTest.handler);
frame2.add(b2);
hello2 = new JLabel("Hello Frame 2");
hello2.setBounds(100,100,100,20);
frame2.add(hello2);
}
}
工作原理:
- 班级:
- 创建构造函数并初始化所有对象.->setLocationRelativeTo(frame2);
- 在第一个类中创建ActionListener类
- 在ActionListener类中,检查按下了哪个按钮,并根据按下了哪个按钮来调用另一个类.
- 最后一次将帧设置为visible(false)并对其进行dispose(),这取决于应该看到哪个帧,不应该看到哪个帧.
- 班级:
- 创建构造函数并初始化所有对象.->setLocationRelativeTo(frame1);
- Change the content pane of your (single)
JFrame
. As far as I know, this is a better practice than switching entire frames/windows. - Use a
Container
, inside your (single)JFrame
, withCardLayout
and just switch cards when desired. As far as I know, this is a better practice than the previous case.
仅此而已.如果您有更好的方法,请告诉我.我只是在网上找不到任何东西.
Thats all. If you there are ways to do it better, then please tell me. I just didn't find anything on the internet.
再见:)
推荐答案
在Swing中,我可以想到其他几种方法(例如,可能还有其他方法):
There are a couple of other ways to do this in Swing that I can think of (ie there may be others too):
情况1的示例:
这有点简单:随时更改 JFrame
的内容窗格,然后重新绘制,并在屏幕中恢复框架的位置(和大小).我不确定,实际上重新绘制甚至重新验证在这里都是可选的,但是当您更改 Component
层次结构时,通常(如果不是每次)都需要它们.
Example for case 1:
This is a bit straight forward: change the content pane of the JFrame
whenever you like, then revalidate, repaint and restore the location (and size) of the frame in the screen. Actually repainting, even revalidating may be optional here, I am not sure, but they are usually (if not everytime) needed when you change the Component
hierarchy.
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.SwingUtilities;
public class MainContentPaneSwitching {
private static class ChangeContentPaneListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
JPanel newFrameContents = new JPanel(); //Uses FlowLayout by default.
newFrameContents.add(new JLabel("You have successfully changed the content pane of the frame!", JLabel.CENTER));
/*We assume that the source is a JButton and that the Window is of type JFrame, hence
the following utility method call is possible without letting any errors appear:*/
JFrame frame = (JFrame) SwingUtilities.getWindowAncestor((JButton) e.getSource());
frame.setContentPane(newFrameContents); //Change the content pane of the frame.
frame.revalidate(); //Notify the frame that the component hierarchy has changed.
frame.pack(); //Resize the frame as necessary in order to fit as many contents as possible in the screen.
frame.setLocationRelativeTo(null); //Place the frame in the center of the screen. As you can tell, this needs its size to calculate the location, so we made sure in the previous line of code that it is set.
frame.repaint(); //Repaint frame with all its contents.
}
}
private static class MainRunnable implements Runnable {
@Override
public void run() {
JButton changeContentPaneButton = new JButton("Click to go to the next content pane!");
changeContentPaneButton.addActionListener(new ChangeContentPaneListener());
JPanel frameContents = new JPanel(); //Uses FlowLayout by default.
frameContents.add(changeContentPaneButton);
JFrame frame = new JFrame("My application");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Tells the frame that when the user closes it, it must terminate the application.
frame.setContentPane(frameContents); //Add contents to the frame.
frame.pack(); //Resize the frame as necessary in order to fit as many contents as possible in the screen.
frame.setLocationRelativeTo(null); //Place the frame in the center of the screen. As you can tell, this needs its size to calculate the location, so we made sure in the previous line of code that it is set.
frame.setVisible(true);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new MainRunnable()); //Swing code must always be used in the Event Dispatch Thread.
}
}
请注意, revalidate
和 repaint
属于 Component
类,这也意味着它们被继承为他们对 JFrame
说(因为 JFrame
是一个 Frame
,这是一个 Window
,这是一个 Container
,它是一个 Component
).通过继承,我的意思是 JFrame
类本身及其实例可以使用它们,就像 JFrame
声明了它们一样.您可能已经知道这一点,为介绍起见,我只是提到它.
Notice that revalidate
and repaint
belong to the class Component
, which also means that they are inherited as they say to the JFrame
(because JFrame
is a Frame
which is a Window
which is a Container
which is a Component
). By inherited I mean that they can be used by the JFrame
class itself and its instances, as if the JFrame
had declared them. You may already know this, I just mention it for the sake of introduction.
LayoutManager
的句柄处理添加到 Container
的每个 Component
的位置和大小.
LayoutManager
s handle the location and size of each Component
added to a Container
.
CardLayout
是 LayoutManager
,它会执行您要查找的切换.每个 card 都是具有所需内容的 Component
,如果将这些 card Component
s添加到包含的CardLayout的容器
,然后您可以告诉 CardLayout
在这些卡片之间进行切换.切换卡就像您描述的切换场景一样,尽管这样做无需更改容器
!无论是内容窗格,还是全新的 JFrame
,它只是更改哪些子 Component
是可见的,哪些不是.
CardLayout
is a LayoutManager
which does the switching you are looking for. Each card is a Component
with whatever contents it needs, and if you add those card Component
s to a Container
which has CardLayout
, then you can tell the CardLayout
to switch between those cards. Switching cards is like switching scenes as you describe it, although it does so without the need to change the Container
! Be it a content pane, be it an entirely new JFrame
, it just changes which child Component
s are visble and which are not.
要使用它,您可以查看以下示例代码(当然,请阅读API文档和相关教程):
To use it, you can have a look at the following example code (and of-course read the API documentation and related tutorials):
import java.awt.CardLayout;
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.SwingUtilities;
public class MainCardLayoutSwitching {
private static class ChangeContentPaneListener implements ActionListener {
private JPanel cardsParent;
public ChangeContentPaneListener(JPanel cardsParent) {
this.cardsParent = cardsParent;
}
@Override
public void actionPerformed(ActionEvent e) {
/*We assume that 'cardsParent' uses a CardLayout, hence the following method call is
possible without letting any errors appear:*/
CardLayout layout = (CardLayout) cardsParent.getLayout();
layout.show(cardsParent, "SUCCESS_CARD"); //Actual content switching.
}
}
private static class MainRunnable implements Runnable {
@Override
public void run() {
JPanel frameContents = new JPanel(new CardLayout());
JButton changeContentPaneButton = new JButton("Click to go to the next card!");
changeContentPaneButton.addActionListener(new ChangeContentPaneListener(frameContents));
final JPanel changeContentPaneButtonParent = new JPanel(); //Uses FlowLayout by default.
changeContentPaneButtonParent.add(changeContentPaneButton);
JLabel successMessageLabel = new JLabel("You have successfully changed the card of the panel!", JLabel.CENTER);
frameContents.add(changeContentPaneButtonParent, "BUTTON_CARD");
frameContents.add(successMessageLabel, "SUCCESS_CARD");
JFrame frame = new JFrame("My application");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Tells the frame that when the user closes it, it must terminate the application.
frame.setContentPane(frameContents); //Add contents to the frame.
frame.pack(); //Resize the frame as necessary in order to fit as many contents as possible in the screen.
frame.setLocationRelativeTo(null); //Place the frame in the center of the screen. As you can tell, this needs its size to calculate the location, so we made sure in the previous line of code that it is set.
frame.setVisible(true);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new MainRunnable()); //Swing code must always be used in the Event Dispatch Thread.
}
}
这篇关于“切换场景"在Java Swing中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!