Ok, this will be rather noobish - I'm making a GUI with the Eclipse Visual Editor (a JFrame开发者_StackOverflow社区 with stuff in it), basically on the left side there are some buttons and textfields etc. and the right side contains 4 JPanels (with some graphics in them).
The problem is, when I resize the gui (the JFrame) during runtime the components inside stay the same (size wise) and I'd want those 4 JPanels to resize with the JFrame, is it possible?
Simple answer - use layout management, including nesting multiple panels with different layouts to get the result you want. You've essentially got two choices: (a) use a layout manager to manage component location and sizing, or (b) do it all manually. You really don't want to do (b).
You might want to start with the layout manager tutorial.
Using a table based layout can make layout significantly easier than the standard layout managers distributed with Java; there are many available for free. Mine is at tech.dolhub.com.
Here's an example (from the help in MatrixLayout, but I don't recall if I ever actually compiled the example code... I expect I did once):
+--------------------------------------------------------------------------------+ + | + Name : |________________________________________________________________| | + | + Address : |________________________________________________________________| | + | + |________________________________________________________________| | + | + |________________________________________________________________| | + | + City : |____________________| State |__| Zip |_____| - |____| | + | + Phone : |___|-|___|-|____| | + | + Notes : | | | | | + | | | | | + | | | | | + | | | | | + | | | | | + |______________________________| |______________________________| | + [BOTTOM-LEFT] [ BOTTOM-RIGHT ] | + | + [ Yes ] [ No ] [ Abort ] | + | +--------------------------------------------------------------------------------+
private void createContent(Container main){
String[] rows,cols; // row/column specification arrays
JPanel phnpnl,cszpnl,btnpnl; // special nested panels
// create components here...
// CREATE MAIN PANEL WITH DESIRED ROWS AND COLUMNS
rows=MatrixLayout.arrayOf(10,"Size=Pref CellAlign=Middle CellInsets=5,0"); // standard row spec
rows[6] ="Size=100% CellAlign=Top CellInsets=5,0"; // note: row 7 ([6] is index)
rows[7] ="Size=Pref CellAlign=Top CellInsets=5,0"; // note: row 8 ([7] is index)
rows[8] ="Size=Pref CellAlign=Top CellInsets=5,0"; // note: row 9 ([8] is index)
cols=MatrixLayout.arrayOf(3 ,"size=Pref CellAlign=Right CellInsets=5,0"); // standard column spec
cols[1] ="Size=50% CellAlign=Left CellInsets=5,0"; // note: col 2 ([1] is index)
cols[2] ="Size=50% CellAlign=Left CellInsets=5,0"; // note: col 3 ([2] is index)
con.setLayout(new MatrixLayout(rows,cols,"Row=Cur Col=Next"));
// CREATE SPECIAL NESTED PANELS
phnpnl=MatrixLayout.singleRowBar(5,false,new DctComponent[]{phnPart1,phnPart2,phnPart3 });
cszpnl=MatrixLayout.singleRowBar(5,1 ,new DctComponent[]{city,createLabel("State"),state,createLabel("Zip"),zip,zipext});
btnpnl=MatrixLayout.singleRowBar(5,true ,new DctComponent[]{yes,no,cancel });
phnpnl.setName("PhonePanel");
cszpnl.setName("CityStateZipPanel");
btnpnl.setName("ButtonPanel");
// ADD COMPONENTS TO MAIN PANEL
con.add(createLabel( "Name :"),"row=Next col=1"); con.add(name ," hAlign=Fill hSpan=2 ");
con.add(createLabel("Address :"),"row=Next col=1"); con.add(address1," hAlign=Fill hSpan=2 ");
con.add(address2,"Row=Next Col=2 hAlign=Fill hSpan=2 ");
con.add(address3,"Row=Next Col=2 hAlign=Fill hSpan=2 ");
con.add(createLabel( "City :"),"row=Next col=1"); con.add(cszpnl ," hSpan=2 ");
con.add(createLabel( "Phone :"),"row=Next col=1"); con.add(phnpnl ," hSpan=2 ");
con.add(createLabel( "Notes :"),"row=Next col=1"); con.add(notes1 ,"Row=Cur Col=2 hAlign=Fill vAlign=Fill ");
con.add(notes2 ,"Row=Cur hAlign=Fill vAlign=Fill ");
con.add(notes3 ,"Row=Next Col=2 hAlign=Left hGroup=NoteButtons");
con.add(notes4 ,"Row=Cur hAlign=Right hGroup=NoteButtons");
con.add(btnpnl ,"row=Next col=1 hAlign=Right hSpan=3");
main.setBorder(new DctEmptyBorder(10));
main.setBackground(SystemColor.window);
}
It depends on how you add your components to the frame, and what layout manager you use. in this example, the four buttons will resize with the window.
JFrame frame = new JFrame();
Container cp = frame.getContentPane();
cp.setLayout(new GridLayout(2, 2));
cp.add(new JButton("one"));
cp.add(new JButton("two"));
cp.add(new JButton("three"));
cp.add(new JButton("four"));
frame.pack();
frame.setVisible(true);
you can use many different layout managers however. read this.
Ok, yeah I know I should use a layout manager etc. but still I chose to build it with the Eclipse Visual Editor (which doesn't have all the layout managers there are) is because I don't have much time for this project and I thought it would be faster that way.
Basically this screen shows how the program should look - some random input/buttons on the left (added random ones for the time being) and the 4 JPanels on the right - they are quite important to me.
screen http://img130.imageshack.us/img130/5282/screenmy.png
Well, it can be terrible work without a Layout manager, but if you want it..... here we go.
- Add a
ComponentListener
to your frame to listen for its resizing, where you can get the size of windows after resizing.
Like:
frame.addComponentListener(new ComponentListener() {
@Override
public void componentShown(ComponentEvent e) {
}
@Override
public void componentResized(ComponentEvent e) {
if (e.getSource() instanceof JFrame) {
JFrame frame = (JFrame)(e.getSource());
frame.repaintElements(frame.getWidth(), frame.getHeight());
}
}
@Override
public void componentMoved(ComponentEvent e) {
}
@Override
public void componentHidden(ComponentEvent e) {
}
});
In your
JFrame
class (in this case you must make it a child class ofJFrame
to add your own method), define arepaintElements(int w, int h)
method, taking the new height and new width as arguments.In
repaintElements(int x, int y)
, implement your logic to change the location and size of every element. I usesetBound(int x, int y, int w, int h)
.x
andy
determines the location of the left top corner of an element, relative to its container, andw
andh
determine its size.
After all I got it to work in my project, but it's all tedious. Think about this:
I have a long label atop, and then a table below, and then another panel below the table, at last a button of exit at right down corner.
First of all, the title label atop. I want it to expand horizontally but not vertically, so in my repaintElements()
I set it like:
label1.setBounds(5, 0, x-5, 30);
so every time the windows changes size, the label is located on the 5 pixels from the very left, 0 pixels from the very top, x-5
pixels of width (to leave some space for the border) and always 30 pixels of height.
Now I have the JScrollPane
containing the JTable
. I want it to expand along with the window, so:
table.setBounds(5, 30, x-15, y-30-60-5);
Because vertically I must leave space for the label above (30 pixels) and the panel below(60 pixels) and the button below(5 pixels), and the location of this table is determined by the height and width of the label above (5 and 30, if without borders...). The table has a vertical scroll so I have to leave space for it, too(so x-15
instead of x-5
. Holy shit.)
And then another panel below. If the window expands, horizontally I want this panel increase too, but not vertically, so:
panel.setBounds(5, y-30-60-5+30, x-10, 60); //the y value is "y coordinate of the element above" + "width of the element above"
At last, the button. I decide not to increase its size, but just let it stay in the corner, so:
button.setBounds(x-20, y-10, 15, 5); //the button is 15*5 pixels. extra space is for border.
Easy? It seems so, but you need a lot of testing........ And if the size of the border changes, another hell of testing... Actually you waste time in some trivial things and soon you get bored. So, use a Layout manager.
Use a layout manager. If you don't use it you'll have to resize it your self ( which would include setting the new location each time )
LayoutManagers seems problematic and actually they are.
In Java 1.6 the GroupLayout manager was added and I think it is quite useful and simple enough.
The power of the layout managers is released when used in conjunctions with others. Here's a A Visual Guide to Layout Managers.
If you post an screenshot of your application I'm pretty sure we can came up with a basic layout that you can work from.
精彩评论