I made a JComponent that displays a rectangle of a specified color. (Haven't found any other way to achieve this effect). Problem is, it doesn't follow JFrame.pack() and Layout Managers as expected.
Code:
import java.awt.*;
import javax.swing.*;
public class FooRunnable implements Runnable{
private class ColorSample extends JComponent{
private Color sampleColor;
private int width, height;
public ColorSample(int rgb, int w, int h){
sampleColor = new Color(rgb);
width = w;
height = h;
}
public Dimension getSize(){
return new Dimension(width, height);
}
public int getWidth(){
return width;
}
public int getHeight(){
return height;
}
public boolean isDisplayable(){
return true;
}
public void paintComponent(Graphics g){
g.setColor(sampleColor);
g.fillRect(0, 0, width, height);
}
}
public void run(){
JFrame mainFrame = new JFrame();
//mainFrame.setSize(500, 300);
Container mainContent = mainFrame.getContentPane();
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainContent.setLayout(new BoxLayout(mainContent, BoxLayout.PAGE_AXIS));
JPanel specifyFilePanel = new JPanel();
specifyFilePanel.setLayout(new BoxLayout(specifyFilePanel, BoxLayout.LINE_AXIS));
JLabel filenameLabel = new JLabel("File: ");
JButton browseButton = new JButton("Browse...");
specifyFilePanel.add(Box.createHorizontalStrut(8));
specifyFilePanel.add(filenameLabel);
specifyFilePanel.add(browseButton);
specifyFilePanel.add(Box.createHorizontalStrut(8));
JPanel colorStatusPanel = new JPanel();
colorStatusPanel.setLayout(new BoxLayout(colorStatusPanel, BoxLayout.Y_AXIS));
JLabel statusLabel = new JLabel("");
JButton roll = new JButton("Operate");
colorStatusPanel.add(new ColorSample(Color.red.getRGB(), 50, 100));
colorStatusPanel.add(statusLabel);
colorStatusPanel.add(roll);
mainContent.add(Box.createVerticalStrut(5));
mainContent.add(specifyFilePanel);
mainContent.add(Box.createVerticalStrut(10));
mainContent.add(colorStatusPanel);
mainContent.add(new JPanel());
mainFrame.pack();
mainFrame.setVisible(true);
}
}
I tried experimenting between pack and explicitly specifying the frame's si开发者_运维百科ze. Here are the default appearances of my GUI on various settings:
Plain mainFrame.pack():
mainFrame.setSize(500, 500):
mainFrame.setSize(500, 300):
The closest to what I intend to achieve is mainFrame.setSize(500, 500) although, as I plan to add a few more components, I expect it will be fragile. As you see, in the other two, the "Operate" button overlaps with the ColorSample Component---like it's not following the Layout Manager I set. And then see how pack cuts of the ColorSample Component. Any tips on how I can achieve the effect I want?
LayoutManagers are free to size/position components as they deem appropriate, components cannot force them but only give hints in their getXXSize (XX == min/pref/max) methods. So the best a component implementation can do is
- implement all getXXSize and return the size they ideally want
- implement paintComponent to cope with a differing size
a snippet only
public class MyBox extends JComponent {
Dimension boxSize;
public void setBoxSize(Dimension box) {
this.boxSize = new Dimension(box);
...
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
// position the box in the actual size
// and paint it
}
@Override
public Dimension getPreferredSize() {
return getBoxSize();
}
@Override // same for min/max
public Dimension getM...Size( {
return getBoxSize();
}
}
pack()
uses getPreferredSize()
of your component. So just return desired size of your rectangle and the size will be used in LayoutManager
.
精彩评论