I have a problem using MigLayout in combination with dynamically changing the font-size of the components which are shown in the MigLayout cells.
In detail: I added a JCheckBox via MigLayout to a JPanel. The font-size of the JCheckBox is default (12pt?) and the row which contains the JCheckBox has a preferred height of 17lp. That all works fine.
(View here: http://www.bilderload.com/bild/227327/migproblemcellheight1UQXP2.png)
Now I change the font-size to e.g. 20pt and start the program again. Now the text of the JCheckBox is cut because the row has also the height of 17lp.
(View here: http://www.bilderload.com/bild/227328/migproblemcellheight2DDPGJ.png)
If I for example let the row definition empty ("[]") the text shows correctly with both font sizes - the normal and the large one. But in this case the row will sadly never reach a minimum of 17lp. (It will always have a minimum of 23lp or so)
How can I change the MigLayout definition to get a minimum row-height of 17lp and to let the cell grow correctly with the components font-size/text etc.?
Or maybe this is a L&F problem?
Thanks & best regards,
Philipp
Here is my sample code (working example):
import java.awt.Font;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
public class TestMigLayoutFontSize extends JFrame {
public TestMigLayoutFontSize() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(600, 400);
setContentPane(getTestPanel());
setVisible(true);
}
private JPanel getTestPanel() {
JCheckBox testBox = new JCheckBox("Program argument");
Font normalFont = testBox.getFont();
Font largeFont = new Font(testBox.getFont().getName(), testBox.getFont().getStyle(), 20);
// testBox.setFont(normalFont);
testBox.setFont(largeFont);
JPanel tempPanel = new JPanel(new MigLayout("debug", "0lp![grow,fill]0lp!", "[17lp:17lp:n]"));
tempPanel.add(testBox);
JPanel testPanel = new JPanel(new MigLayout("", "[grow,fill]", "[grow,fill]"));
testPanel.add(tempPanel);
return testPanel;
}
public static void main(String[] args) {
new TestMigLayoutFontSize();
}
}
You may reduce the space around your checkbox by reducing the border size, e.g. put
testBox.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
directly after the assignment of testBox. You may then leave the row definition empty and still get a reasonable height for your panel.
The following works for me. I think the problem is , that you specify the preferred size.
Regards
Roger
package de.test;
import java.awt.Font;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
public class MigTest extends JFrame {
public MigTest() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(600, 400);
setContentPane(getTestPanel());
setVisible(true);
}
private JPanel getTestPanel() {
JCheckBox testBox = new JCheckBox("Program argument");
Font normalFont = testBox.getFont();
Font largeFont = new Font(testBox.getFont().getName(), testBox.getFont().getStyle(), 90);
// testBox.setFont(normalFont);
testBox.setFont(largeFont);
JPanel tempPanel = new JPanel(new MigLayout("debug", "0lp![grow,fill]0lp!", "[80:n:]"));
tempPanel.add(testBox);
JPanel testPanel = new JPanel(new MigLayout("", "[grow,fill]", "[grow,fill]"));
testPanel.add(tempPanel);
return testPanel;
}
public static void main(String[] args) {
new MigTest();
}
}
Related
I am trying to create a simple Java Swing GUI that consists of a panel on top and tabs in the center. I want the top panel to remain its preferred size and the tabs to take up the remaining space so I used a BorderLayout. The content of the tab can be tall so I put the tab component into a scroll pane.
Everything seems to work the way I expect (with respect to component sizing and scroll bar behavior when I resize the frame) except that my packed frame is 12 pixels too tall (and possibly 16 pixels too wide). Would someone please explain what is going on and how to resolve it. Somehow when the pack is sizing all of the components, something is smart enough to (mostly) respect the screen size. I am using Java 8 on Windows 7 with a screen resolution of 1920 x 1200.
Below is my test code and the output it produces.
Code:
package test;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
public final class SizeTest
{
public static void main(final String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
createAndShowGui();
}
});
}
private static void createAndShowGui()
{
final JPanel topPanel = new JPanel();
topPanel.setBorder(BorderFactory.createTitledBorder("Top"));
topPanel.setPreferredSize(new Dimension(800, 150));
final JPanel centerPanel = new JPanel();
centerPanel.setBorder(BorderFactory.createTitledBorder("Center"));
centerPanel.setPreferredSize(new Dimension(800, 1300));
final JScrollPane scrollPane = new JScrollPane(centerPanel);
final JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.addTab("Tab", scrollPane);
final JPanel mainPanel = new JPanel(new BorderLayout(0, 10));
mainPanel.add(topPanel, BorderLayout.NORTH);
mainPanel.add(tabbedPane, BorderLayout.CENTER);
final JFrame mainFrame = new JFrame("Size Test");
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.add(mainPanel);
mainFrame.pack();
System.err.println("***** Frame Size: " + mainFrame.getSize() + ", Screen Size: "
+ Toolkit.getDefaultToolkit().getScreenSize() + ", Maximum Window Bounds: "
+ GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds());
mainFrame.setVisible(true);
}
}
Output:
***** Frame Size: java.awt.Dimension[width=816,height=1212], Screen Size: java.awt.Dimension[width=1920,height=1200], Maximum Window Bounds: java.awt.Rectangle[x=0,y=0,width=1920,height=1156]
If you're going to stuff around with setPreferredSize, be prepared for things to go astray.
The first thing I would do, is seriously reconsider using setPreferredSize.
Because of the way the API works, JScrollPane will use the preferredSize of the component to make determinations about it's own size. You can change this by implementing the Scrollable interface, which allows you to return the preferredScrollableViewportSize, which JScrollPane will use instead when determing how large it needs to be
You see Scrollable demonstrated here and here and lots of other places if you do some searching
I'm currently working on an irc bot and today I would like to create a GUI for it.
I'm trying to create a column layout that has two parts, left and right.
The left side will show console output, the right will contain all the controls (joining channels, commands etc).
I'm having issues creating the two columns. I have a JPanel that is the whole width and height of the window and has a border of 10 pixels, and then I have two panels within that; left and right.
The left and right panels are for some reason taking the whole size of the window, and the right panel is overlapping everything.
Here's an example picture: http://i.imgur.com/lc4vHVH.png
The white is the right panel, it should only be half the size and have an identical but black panel on the left of it.
Here's my current code, sorry if it's messy, new to the whole Swing GUI.. Thanks for any help.
package tk.TaylerKing.GribbyBot;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.HashMap;
import javax.swing.BorderFactory;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import com.alee.laf.WebLookAndFeel;
import com.alee.laf.menu.WebMenuBar;
import com.alee.laf.menu.WebMenuItem;
import com.alee.laf.panel.WebPanel;
import com.alee.laf.rootpane.WebFrame;
public class GribbyBot extends WebFrame {
private static final long serialVersionUID = 4641597667372956773L;
public static HashMap<String, ArrayList<String>> connections = new HashMap<String, ArrayList<String>>();
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(WebLookAndFeel.class.getCanonicalName());
SwingUtilities.invokeLater(new Runnable(){
public void run(){
GribbyBot gb = new GribbyBot();
gb.setVisible(true);
}
});
}
public GribbyBot(){
WebPanel panel = new WebPanel();
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
panel.setPreferredSize(new Dimension(780, 580));
WebMenuBar menu = new WebMenuBar();
WebMenuItem file = new WebMenuItem("Exit");
file.setMnemonic(KeyEvent.VK_E);
file.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
menu.add(file);
setJMenuBar(menu);
WebPanel left = new WebPanel();
left.setPreferredSize(new Dimension(380, 580));
left.setBackground(Color.BLACK);
WebPanel right = new WebPanel();
right.setPreferredSize(new Dimension(380, 580));
right.setBackground(Color.WHITE);
add(panel);
panel.add(left);
panel.add(right);
setTitle("GribbyBot");
setSize(800, 600);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setResizable(false);
}
}
On a side note, all the variables that are prefixed with "Web" are the same as Swing, but it's a custom GUI.
Override JComponent#getPreferredSize() instead of using setPreferredSize()
Read more Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?
If extremely needed in case of Performing Custom Painting then try in this way:
Sample code:
final JPanel panel = new JPanel(){
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
// your custom painting code here
}
#Override
public Dimension getPreferredSize() {
return new Dimension(40, 40);
}
};
Why are using setPreferredSize() method whereas you can achieve this design easily using any proper layout such as BoxLayout, GridLayout, BorderLayout etc.
Read more about layout How to Use Various Layout Managers
EDIT
try JPanel panel = new JPanel(new GridLayout(1,2));
I am rather new to this whole Swing, but nevertheless it already got me quite annoyed.
I am trying to do something simple, that behaves like WPF's list with custom item template. That is, item are of fixed size and as it overflows the given area a scroll bar pops up.
And I've been trying and trying, but I just can't get it to work. The closest I got was with BoxLayout, the problem there however, is that if there are too few items to take available space, they get stretched -.-
I bet there is some simple way to achieve that, I just don't know about. Thanks in advance.
Here's the code I got (java):
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class App
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new MainFrame();
}
});
}
}
class MainFrame extends JFrame
{
private JPanel itemsPanel;
private JButton addButton;
public MainFrame()
{
// create components
itemsPanel = new JPanel();
addButton = new JButton("Add");
// layout
itemsPanel.setLayout(new BoxLayout(itemsPanel, BoxLayout.Y_AXIS));
JPanel buttons = new JPanel(new FlowLayout(FlowLayout.LEFT));
buttons.add(addButton);
setLayout(new BorderLayout());
add(new JScrollPane(itemsPanel), BorderLayout.CENTER);
add(buttons, BorderLayout.SOUTH);
// actions
addButton.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent arg0)
{
itemsPanel.add(new SampleItem());
itemsPanel.revalidate();
}
});
// frame size and close action
setDefaultCloseOperation(EXIT_ON_CLOSE);
Dimension size = new Dimension(300, 300);
setMinimumSize(size);
setSize(size);
setVisible(true);
}
}
class SampleItem extends JPanel
{
public SampleItem()
{
setBorder(BorderFactory.createLineBorder(Color.black));
setPreferredSize(new Dimension(200, 100));
}
}
EDIT:
I ended up writing custom renderer and editor thanks to rcook's answer.
EDIT2:
Eh, after turning it in, I got scolded really badly for this... Apparently the problem is that JScrollPane resizes viewport so that the control fills all available space and the solution is to create JPanel implements Scrollable and return false in public boolean getScrollableTracksViewportHeight(). Oh well, I hope someone will find it useful, editors are just so much pain.
Use a JList, put it inside a JScrollPane, put that within a pane in the middle part of a BorderLayout; BorderLayout is the default for a JFrame, so you may not need to create one. Put the lower button on the bottom portion of the BorderLayout.
I have a JTabbed pane, which has a varying number of tabs. When the number of tabs is greater than 4, I get extra spacing/padding at the bottom of each tab panel. The picture below shows this (on the left you see the extra spacing, on the right you see no extra spacing).
Here is the exact code I used to get those pictures:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
public class DialogTest {
public static void main(String[] args) {
new DialogTest();
}
public DialogTest() {
JDialog dialog = new MyDialog();
dialog.pack();
dialog.setVisible(true);
}
class MyDialog extends JDialog {
public MyDialog() {
super(null, ModalityType.APPLICATION_MODAL);
final JTabbedPane tabs = new JTabbedPane();
final int numTabs = Integer.parseInt(JOptionPane.showInputDialog("Number of tabs:"));
setPreferredSize(new Dimension(400, 200));
for (int i = 1; i <= numTabs; i++) {
tabs.addTab("Tab"+i, new MyPanel(i));
}
setLayout(new BorderLayout());
add(tabs, BorderLayout.NORTH);
}
}
class MyPanel extends JPanel {
public MyPanel(int text) {
final JLabel label = new JLabel("THIS IS A PANEL" + text);
label.setFont(label.getFont().deriveFont(18f));
label.setBackground(Color.cyan);
label.setOpaque(true);
add(label);
setBackground(Color.red);
}
}
}
I've tried numerous things including many different layout managers. I can't for the life of me get rid of that extra spacing. Any help would be great.
final JTabbedPane tabs = new JTabbedPane();
tabs.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); // ADD THIS!
The reason the other example behaves as it does is that the pane wraps the tabs to the next line & presumes that once we have gone beyond as many tabs as it might naturally display in a single line, it must increase the preferred size to include that extra line of tabs.
I'm trying to create two JLabels - one for icon (UIManager.getIcon("OptionPane.informationIcon") - one of Java's standart icons) and one for text. Sure, I know there is a JLabel's constructor which can make one label from icon and text, but I need exactly two labels, because one of them should be highlighted when mouse moves through it, I omit this part of code.
The problem is I can't find out how to change Icon size. At least I want to set manually height of icon, but it would be better if its height calculated automatically to fit text with specified font. I spent several hours trying to find information in the Web, but couldn't find anything relative.
I tried to implement Icon class and override getIconHeight() and getIconWidth() methods, but I don't know what to do next with my Icon object, because Icon is an interface so it has no constructors.
Here is my simplified code:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import net.miginfocom.swing.MigLayout;
public class AppView
{
private final JFrame main_frame;
public AppView()
{
main_frame = new JFrame();
main_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
main_frame.setTitle("Example");
JPanel main_panel = new JPanel() {
private static final long serialVersionUID = 1L;
public Dimension getPreferredSize()
{
return new Dimension(200, 200);
}
};
main_frame.getContentPane().add(main_panel, BorderLayout.CENTER);
main_panel.setLayout(new MigLayout());
JLabel label_icon = new JLabel(UIManager.getIcon("OptionPane.informationIcon"));
JLabel label_text = new JLabel("Text goes here");
label_text.setFont(new Font("sans-serif", Font.PLAIN, 12));
main_panel.add(label_icon);
main_panel.add(label_text);
main_frame.pack();
main_frame.setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new AppView();
}
});
}
}
Here is the result, as you can see, Icon is higher than text:
Thanks in advance!