使用 JPanel Java 自动调整 JFrame 的大小
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19180372/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
resize JFrame automatically with JPanel Java
提问by Ange King
I am implementing changes to a minesweeper game. One of these things is the difficulty. I have managed to do this and its working, but as the game board (in its own Jpanel) gets bigger & smaller (depending on the difficulty), I cannot get the JFrame to resize automatically. I am using:
我正在对扫雷游戏进行更改。其中之一就是困难。我已经设法做到了这一点及其工作,但是随着游戏板(在它自己的 Jpanel 中)变得越来越大(取决于难度),我无法让 JFrame 自动调整大小。我在用:
setPreferredSize(new Dimension(WIDTH, HEIGHT));
to set the initial size of the window, but this makes it REALLY tiny, as in only showing the word 'File' from the JMenuBar. I have to resize it manually.
设置窗口的初始大小,但这使得它非常小,因为只显示 JMenuBar 中的“文件”一词。我必须手动调整它的大小。
I tried setSize() and things like frame.pack() on the ActionListener event, but I cannot seem to get it to resize.
我在 ActionListener 事件上尝试了 setSize() 和 frame.pack() 之类的东西,但我似乎无法调整它的大小。
Any tips on what code/methods to use.
关于使用什么代码/方法的任何提示。
edit: code posted
编辑:发布的代码
package mines;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class SetupFrame extends JFrame {
private final int WIDTH = 600;
private final int HEIGHT = 500;
public JFrame frame;
public JMenuBar menubar;
public JMenu file;
public JMenu levels;
public JMenu help;
public JMenuItem login;
public JMenuItem save;
public JMenuItem resume;
public JMenuItem exit;
public JMenuItem easy;
public JMenuItem medium;
public JMenuItem hard;
private JLabel statusbar;
public JPanel main;
public JPanel buttonPanel;
public JPanel saved;
public JPanel game;
public Board mineGame;
public JButton ngButton;
public JButton undoButton;
public JButton redoButton;
public JTabbedPane tp;
public String[] levelPicker;
public JComboBox levelSelect;
public JFileChooser chooser;
public String filename;
public int difficulty;
public SetupFrame(){
frame = new JFrame();
String filename = JOptionPane.showInputDialog(frame, "Enter Your Name.");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setTitle("Minesweeper");
//menubar, menus, menu items
menubar = new JMenuBar();
setJMenuBar(menubar);
file = new JMenu("File");
help = new JMenu("Help");
menubar.add(file);
menubar.add(help);
login = new JMenuItem("Login..");
save = new JMenuItem("Save..");
resume = new JMenuItem("Resume..");
exit = new JMenuItem("Exit");
file.add(login);
file.add(save);
file.add(resume);
file.addSeparator();
file.add(exit);
statusbar = new JLabel("");
chooser = new JFileChooser(); // new File Chooser for saved tab
undoButton = new JButton(" Undo "); //undo Button for game panel
ngButton = new JButton(" New Game ");//new game Button for game panel
redoButton = new JButton(" Redo");//redo Button for game panel
main = new JPanel(new BorderLayout()); //new panel for main game
//main.add(mineGame, BorderLayout.CENTER); //add instance mineGame to main panel
game = new JPanel(new BorderLayout());// new panel for game tab
main.add(game, BorderLayout.CENTER); //add the mineGames panel to game panel
game.add(statusbar, BorderLayout.SOUTH); //add statusbar to bottom of game panel
//game.add(button, BorderLayout.NORTH); // add buttons (eventually be redo, undo, new game)
saved = new JPanel(); // create new panel for the saved tab
saved.add(chooser);//add the File Chooser to the saved tab
String[] levelPicker = {"Easy", "Medium", "Hard"};
levelSelect = new JComboBox(levelPicker);
levelSelect.setSelectedIndex(0);
//levelSelect.addActionListener(this);
buttonPanel = new JPanel();
buttonPanel.add(undoButton);
buttonPanel.add(ngButton);
buttonPanel.add(redoButton);
buttonPanel.add(levelSelect);
main.add(buttonPanel, BorderLayout.NORTH);
//create & add the tabs
tp = new JTabbedPane();
tp.addTab ("Game", main);
tp.addTab ("Saved", saved);
tp.addTab ("Statistics", null);
add(tp);
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setResizable(true);
setVisible(true);
frame.pack();
class listener implements ActionListener{
public void actionPerformed (ActionEvent e)
{
if(e.getSource() == ngButton){
//JOptionPane.showInputDialog(frame, "Do You want To Save");
newMineGame();
}
JComboBox cb = (JComboBox)e.getSource();
String picker = (String)cb.getSelectedItem();
if (picker == "Easy"){
difficulty = 0;
newMineGame();
}
if (picker == "Medium"){
difficulty = 1;
newMineGame();
frame.pack();
}
if (picker == "Hard"){
difficulty = 2;
newMineGame();
frame.pack();
}
}
private void newMineGame() {
game.removeAll();
mineGame = new Board(statusbar, difficulty);
game.add(mineGame, BorderLayout.CENTER);
game.add(statusbar, BorderLayout.SOUTH);
repaint();
}
}
ngButton.addActionListener(new listener());
undoButton.addActionListener(new listener());
redoButton.addActionListener(new listener());
levelSelect.addActionListener(new listener());
}
public static void main(String[] args) {
new SetupFrame();
}
回答by mKorbel
One of these things is the difficulty. I have managed to do this and its working, but as the game board (in its own Jpanel) gets bigger & smaller (depending on the difficulty), I cannot get the JFrame to resize automatically.
其中之一就是困难。我已经设法做到了这一点及其工作,但是随着游戏板(在它自己的 Jpanel 中)变得越来越大(取决于难度),我无法让 JFrame 自动调整大小。
and
和
tried setSize() and things like frame.pack() on the ActionListener event, but I cannot seem to get it to resize.
在 ActionListener 事件上尝试了 setSize() 和 frame.pack() 之类的东西,但我似乎无法调整它的大小。
JFrame.pack()
works in casethat all
JComponents
representing mines (there is best of ways to useJToggleButton
) returns properlyPreferredSize
back to its parent (JPanel
)parent (JPanel) laid by GridLayout (very simple)
and there are two ways how, when, where to
JFrame.pack()
use
CardLayout
, the next code line after swithchingCard
isJFrame.pack()
remove old
JPanel
(fromJFrame
) and replace with new, then you need to callJFrame.(re)validate()
,JFrame.repaint()
andJFrame.pack()
as last code lines
maybe there is another issue, important is code ordering in the case that is there settings for
JFrame.setResizable(false);
JFrame.pack()
以防万一所有
JComponents
代表地雷(有最好的使用方法JToggleButton
)正确PreferredSize
返回其父级(JPanel
)GridLayout 放置的 parent (JPanel)(非常简单)
有两种方式如何、何时、何地
JFrame.pack()
使用
CardLayout
,切换后的下一行代码Card
是JFrame.pack()
删除旧的
JPanel
(从JFrame
)并替换为新的,然后您需要调用JFrame.(re)validate()
,JFrame.repaint()
并JFrame.pack()
作为最后的代码行
也许还有另一个问题,重要的是代码排序在有设置的情况下
JFrame.setResizable(false);
after your edit
编辑后
use Cardlayout
there you miss code lines (don't to extends
JFrame
, create this Object asLocal variable
)JFrame.(re)validate()
,JFrame.repaint()
andJFrame.pack()
as last code lines inprivate void newMineGame() {
在那里你错过了代码行(不要扩展
JFrame
,将此对象创建为Local variable
)JFrame.(re)validate()
,JFrame.repaint()
以及JFrame.pack()
最后的代码行private void newMineGame() {
but I dont understand what you mean by: "there you miss code lines (don't to extends JFrame, create this Object as Local variable) ;
但我不明白你的意思:“你错过了代码行(不要扩展 JFrame,将此对象创建为局部变量);
code could be
代码可能是
import javax.swing.*;
public class SetupFrame {
private JFrame frame;
private JMenuBar menubar = new JMenuBar();
private Board mineGame;
public SetupFrame() {
//there add required JComponents
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setTitle("Minesweeper");
frame.setJMenuBar(menubar);
frame.add(mineGame);
//frame.setPreferredSize(new Dimension(WIDTH, HEIGHT));
//frame.setResizable(true);//not neccessary
frame.pack();
frame.setVisible(true);
}
private void newMineGame() {
//remove old Board
//add a new Board
frame.validate();
frame.repaint();
frame.pack();
}
private static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new SetupFrame();
}
});
}
}
回答by dic19
Here is your mistake:
这是你的错误:
frame.pack();
frame.pack();
Why do you need frame
if your SetupFrame
actually extends from JFrame
? Change this line by just pack()
and it will work.
frame
如果您SetupFrame
实际上从 扩展,为什么需要JFrame
?仅更改此行,pack()
它将起作用。
@mKorbel already posted a complete and very useful explanation about pack()
behavior (thank you).
@mKorbel 已经发布了关于pack()
行为的完整且非常有用的解释(谢谢)。
Update
更新
Also in your listener
class you'll get this exception when a JButton
is pressed:
同样在你的listener
班级JButton
中,按下a 时你会得到这个异常:
java.lang.ClassCastException: javax.swing.JButton cannot be cast to javax.swing.JComboBox
You need make this little change to avoid this:
你需要做这个小小的改变来避免这种情况:
class listener implements ActionListener{
public void actionPerformed (ActionEvent e) {
if(e.getSource() == ngButton){
//JOptionPane.showInputDialog(frame, "Do You want To Save");
newMineGame();
} else if(e.getSource() instanceof JComboBox){ // add this else-if block
JComboBox cb = (JComboBox)e.getSource();
String picker = (String)cb.getSelectedItem();
if (picker.equals("Easy")){ // <-- picker == "Easy" is not the proper way to compare string, use equals() method instead
difficulty = 0;
newMineGame();
}
if (picker.equals("Medium")){
difficulty = 1;
newMineGame();
//frame.pack(); <--- again, just use pack();
pack();
}
if (picker.equals("Hard")){
difficulty = 2;
newMineGame();
//frame.pack(); <--- again, just use pack();
pack();
}
}
}
Or even better, implement an ItemListenerto listen JComboBox
selection changes instead using an ActionListener
或者甚至更好,实现一个ItemListener来监听JComboBox
选择更改而不是使用ActionListener