I have read many subjects here but I can't make my window with the layout I want.
I simply want all my graphic object to be in a row style like in the first picture here : http://docs.oracle.com/javase/tutorial/uiswing/layout/box.html
I've tried GridLayout but it still make my first button giant and then, as I add textfields, it's getting smaller and smaller?!
Here is my code without all the imports:
public class TestScrollPane extends JFrame implements ActionListener{
Dimension dim = new Dimension(200 , 50);
JButton button;
JPanel panel = new JPanel();
JScrollPane scrollpane = new JScrollPane(panel);
public TestScrollPane(){
scrollpane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
this.add(scrollpane);
//panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
this.setSize(300, 400);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
button = new JButton("click me");
button.setPreferredSize(dim);
panel.add(button);
button.addActionListener(this);
}
public void actionPerformed(ActionEvent e){
if(e.getSource() == button ){
JTextField txt = new JTextField(); // we add a new button
txt.setPreferredSize(dim);
panel.add(txt);
SwingUtilities.updateComponentTreeUI(this); // refresh jframe
}
}
public static void main(String[] args){
TestScrollPane test = new TestScrollPane();
}
}
I just want to have one button per row.
A BoxLayout will respect the minimum/maximum sizes of a component.
For some reason the maximum height of a text field is unlimited so the text field gets all the space available.
So you can do something like:
JTextField txt = new JTextField(10); // we add a new button
//txt.setPreferredSize(dim); // don't hardcode a preferrd size of a component.
txt.setMaximumSize(txt.getPreferredSize());
Also:
//SwingUtilities.updateComponentTreeUI(this); // refresh jframe
Don't use the above method. That is used for a LAF change.
Instead when you add/remove components from a visible GUI you should use:
panel.revalidate();
panel.repaint();
Related
I am creating a GUI using GridLayout to arrange multiple panels that are using FlowLayout. I am using pack to determine the size of the frame. If I have only a TextArea then it sizes correctly. If I have only other components it sizes correctly. But if I use both p1 and p2 in the code below the panel with the buttons does not size properly. The test code I am using is below. If I use only p1 or p2 it sizes properly, but not with both: Here is the image I am getting. I don't want all that extra space between the buttons and the textarea.
If I do textarea alone it sizes properly.:
public class GUIPractice extends JFrame
{
//declare GUI objects
JPanel panel;
JPanel p1, p2;
JButton btnAdd, btnShow;
JScrollPane js;
JTextArea taOutput;
//constructor
public GUIPractice()
{
//give frame a title
setTitle("GUI Practice");
panel =new JPanel(new GridLayout(0, 1));
btnAdd = new JButton("Add");
btnShow = new JButton("Show");
taOutput = new JTextArea(10, 20);
js = new JScrollPane(taOutput, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
p1 = new JPanel();
p1.add(btnAdd);
p1.add(btnShow);
p2 = new JPanel();
p2.add(js);
panel.add(p1);
panel.add(p2);
//add the panel to the frame
add(panel);
}
public static void main(String[] args)
{
GUIPractice frame = new GUIPractice();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
It sizes correctly. The GridLayout means that all cells will be the same size. Since the text area is bigger than the buttons, you see extra space in the panel containing the buttons.
I would suggest you just use the default BorderLayout of the frame.
There is no need for your "panel" using the GridLayout.
You just use:
add(p1, BorderLayout.PAGE_START);
add(p2, BorderLayout.CENTER);
Now the p1 and p2 will be the proper height.
Also, there really is no need for "p2". You can just add the scroll pane directly to the frame.
I am developing a Java Application that uses a JTable for capturing user input. The user will have to print data captured in the table. I would want the user to open multiple documents to work on. This I have implemented it this way: I have my JFrame as my main window; on to this JFrame, I have added JTabbedPane so that the user can switch between File, Settings and Tools.Upon clicking new File, the user is taken to a JTabbedPane(place at the center of the JFrame) with a JTable for input. I would want that the next time the user click new File, a new JPanel would be added to the JTabbledPane; but this new JPanel should also contain the JTable for input.This behavior should continue everytime the user creates a new File. This is shown in the images that I have uploaded.(Please forgive for poor drawing).
I have achied this by this code:
public final class QuotPane {
//components to be used
JFrame frame;
JTabbedPane tabbedPane,tablePane;
JPanel quotPane, topPane, pane1, pane2, pane3,tablePanel;
JSeparator sep;
JButton newFile;
QuotPane() {
this.createQuotPane();
this.createGUI();
ButtonActionListener lits= new ButtonActionListener();
newFile.addActionListener(lits);
}
public void createGUI() {
tabbedPane = new JTabbedPane();
tabbedPane.addTab("Create Quot", quotPane);
frame = new JFrame("Qout Interface");
frame.setSize(new Dimension(700, 650));
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
//adding the tabbed pane to the frmae
frame.add(tabbedPane, BorderLayout.NORTH);
}
public void createQuotPane() {
quotPane = new JPanel();
quotPane.setLayout(new BorderLayout());
//creating the top pane
topPane = new JPanel();
topPane.setPreferredSize(new Dimension(650, 145));
topPane.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED, Color.lightGray, Color.lightGray, Color.white, Color.orange));
topPane.setLayout(new MigLayout());
//add the top pane on the quot panel
quotPane.add(topPane, BorderLayout.NORTH);
//adding the panes on the top pane
this.createPanels();
topPane.add(pane1);
topPane.add(pane2);
topPane.add(pane3);
}
//a method to create panes for options
public void createPanels() {
pane1 = new JPanel();
pane1.setPreferredSize(new Dimension(200, 140));
pane1.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED, Color.BLUE, Color.lightGray, Color.white, Color.orange));
//lets set the icons then
pane1.setLayout(new MigLayout());
Icon fileIcon = new ImageIcon(this.getClass().getResource("/images/fil.jpg"));
newFile = new JButton(fileIcon);
pane1.add(new JLabel("New File"), "wrap");
pane1.add(newFile,"width 20!");
pane2 = new JPanel();
pane2.setPreferredSize(new Dimension(200, 140));
pane2.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED, Color.BLUE, Color.lightGray, Color.white, Color.orange));
pane3 = new JPanel();
pane3.setPreferredSize(new Dimension(200, 140));
pane3.setMaximumSize(new Dimension(300, 140));
pane3.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED, Color.BLUE, Color.lightGray, Color.white, Color.orange));
}
public static void main(String[] args) {
QuotPane qp = new QuotPane();
}
public void createTablePane(){
tablePanel= new JPanel();
}
class ButtonActionListener implements ActionListener{
protected int count=0;
#Override
public void actionPerformed(ActionEvent e) {
if(count==0){
if(e.getSource().equals(QuotPane.this.newFile)){
tablePane=new JTabbedPane();
QuotPane.this.createTablePane();
tablePane.addTab("New Qout", tablePanel);
frame.add(tablePane,BorderLayout.CENTER);
count ++;
}
}else if(count>0)
{
tablePane.add("New Quote",new JPanel());
}}}}
The challenge I am facing here is that I cannot add my JTable to every panel created at run time.I have tried this: tablePane.add("New Quote",myCreatedBeforePanleWithTable) but it is overriding the previous tab.
Here are images of things that I want.I read about JDeskTopPane and JInternalFrame, but can't figure out how to make it work the way I want.
How do I make it work the way I want as shown in the image?
Unfortunately, a Swing Component can only have a single parent. If you add Component A to JPanel X and then to JPanel Y, it will end up in Y.
You will need to have three separate JTables, all sharing a single TableModel. This should be fairly straightforward to implement the basic functionality. It might get tricky if you allow sorting and column reordering and you want that to affect all 3 tables.
Could you tell me please, why components like JPanel etc. are not visible when added to a JFrame? Here is my code:
public class GUI{
static JPanel panel = new JPanel();
private void createAndShowGUI() {
final ImageIcon zielonaikona = new ImageIcon("kulazielona.png");
JFrame frame1 = new JFrame("MasterMind");
JRadioButton zielony = new JRadioButton(zielonaikona);
zielony.setSelected(true);
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton akceptuj = new JButton("Akceptuj");
akceptuj.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
JLabel label2 = new JLabel(zielonaikona);
panel.add(label2);
}
});
BoxLayout layout = new BoxLayout(panel, BoxLayout.Y_AXIS);
panel.add(akceptuj);
panel.setLayout(layout);
panel.add(zielony);
JLabel label = new JLabel (zielonaikona);
panel.add(label);
frame1.getContentPane().add(panel);
frame1.getContentPane().add(akceptuj);
frame1.getContentPane().add(zielony);
frame1.setSize(200, 300);
frame1.setVisible(true);
}
public static void main(String[] args) {
GUI kk = new GUI();
kk.createAndShowGUI();
}
}
You add your controls to the JFrame as well as the JPanel panel, so they will only appear in the last container to which they were added, namely the frame. Also because you add them in the default BorderLayout.CENTER position each one displaces the last so you are only left with one component displayed (the JRadioButton zielony)
To fix, remove the lines:
frame1.getContentPane().add(akceptuj);
frame1.getContentPane().add(zielony);
Aside: When adding new components on the fly (i.e. the JLabel added in the ActionListener), don't forget to call:
panel.revalidate();
panel.repaint();
The button and the radio button are added twice, to the panel and to the frame. You didn't set the layout on the frame but I think it has a default one. I just don't remember what kind.
Here is your code that is wrong.
panel.add(akceptuj);
panel.add(zielony);
and
frame1.getContentPane().add(akceptuj);
frame1.getContentPane().add(zielony);
I am trying to implement JTabbedPane. In the following code I have presented a case very similar to what I want to implement. I have created a tab by adding a JPanel to the JTabbedPane. I have added a JButton and JScrollPane to the JPanel. On click of the JButton I want to add a new JPanel having some JRadioButtons to the JScrollPane. But these are not shown even after refreshing the JScrollPane or main JPanel. Please help. The code is given below.
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Test {
static JFrame frame;
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
//Create and set up the window.
frame = new JFrame("DynamicTreeDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTabbedPane tp = new JTabbedPane();
final JScrollPane jsp = new JScrollPane();
JPanel jp = new JPanel();
JButton jb = new JButton("Refresh");
jb.setActionCommand("Show");
jb.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equalsIgnoreCase("Show")){
JRadioButton jrb1 = new JRadioButton("First Option");
JRadioButton jrb2 = new JRadioButton("Second Option");
JRadioButton jrb3 = new JRadioButton("Third Option");
ButtonGroup bg = new ButtonGroup();
bg.add(jrb1);
bg.add(jrb2);
bg.add(jrb3);
JPanel p = new JPanel(new GridLayout(0,1));
p.add(jrb1);
p.add(jrb2);
p.add(jrb3);
jsp.add(p);
jsp.revalidate();
jsp.repaint();
}
}
});
jp.setLayout(new GridLayout(0,1));
jp.add(jb);
jp.add(jsp);
tp.add("First Tab", jp);
frame.getContentPane().add(tp);
//Display the window.
frame.pack();
frame.setVisible(true);
}
}
To add something to JScrollPane use its JViewport rather than directly calling add(). In your example replace:
jsp.add(p);
with:
jsp.getViewport().add(p);
Alternatively, initialize JScrollPane with a JPanel that holds other components. Based on your example:
final JPanel panel = new JPanel();
final JScrollPane jsp = new JScrollPane(panel);
panel.add(new JRadioButton("First Option"));
panel.add(new JRadioButton("Second Option"));
panel.add(new JRadioButton("Third Option"));
See How to Use Scroll Panes for more details.
The components should be added to the JPanel called jp rather than directly to the scroll pane.
JScrollPane only works with a single "View". You cannot add components to the scrollPane. If you want, you can change the "View" using setViewPortView(). To achieve the behaviour you are looking for, do the following:
JPanel centralView = new JPanel();
// possibly configure that central view with appropriate layout and other stuffs
JScrollPane jsp = new JScrollPane(centralView);
...
// Now you can add your components to centralView instead of your jsp.add(...) calls.
You should add the JPanel to the JScollPanes viewport using getViewport(), then repack the JFrame to get the sizing issue sorted using pack();:
jsp.getViewport().add(p);
frame.pack();
instead of:
jsp.add(p);
jsp.revalidate();
jsp.repaint();
Right, I have a JTabbedPane that has a JPanel that contains a JLabel and a JTextField.
my code
JTabbed Pane declaration :
this.tabPane = new JTabbedPane();
this.tabPane.setSize(750, 50);
this.tabPane.setLocation(10, 10);
tabPane.setSize(750,450);
tabPane.add("ControlPanel",controlPanel);
textfield declaration :
this.channelTxtFld = new JTextField("");
this.channelTxtFld.setFont(this.indentedFont);
this.channelTxtFld.setSize(200, 30);
this.channelTxtFld.setLocation(200, 10);
JLabel :
this.channelLabel = new JLabel("Channel name : ");
this.channelLabel.setSize(150, 30);
this.channelLabel.setLocation(10,10);
private void createPanels() {
controlPanel = new JPanel();
controlPanel.setSize(650,500);
}
private void fillPanels() {
controlPanel.add(channelLabel);
controlPanel.add(channelTxtFld);
}
So what my plan is, was to have a tabbed pane that has a JPanel where I have some Labels, textfields and buttons on fixed positions, but after doing this this is my result:
http://i.stack.imgur.com/vXa68.png
What I wanted was that I had the JLabel and next to it a full grown JTextfield on the left side not in the middle.
Anyone any idea what my mistake is ?
thank you :)
What kind of Layout Manager are you using for your controlPanel, you probably want BorderLayout, putting the Label in the West, and the TextField in the center.
BTW, setting the size and position of various components doesn't make sense unless you are using a Null Layout, which isn't a good idea. So i'd remove all that stuff and let the Layout Manager do it for you.
Use a LayoutManager and consider also the methods setPreferredSize, setMinimumSize, setMaximumSize to adjust components bounds according on which is your desired effect.
Assuming the default JPanel layout, FlowLayout, give the JTextField a non-zero number of columns, and give the JLabel a JLabel.LEFT constraint.
Addendum:
a full grown JTextField
Something like this?
import java.awt.*;
import javax.swing.*;
/**
* #see http://stackoverflow.com/questions/5773874
*/
public class JTabbedText {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
private final JTabbedPane jtp = new JTabbedPane();
#Override
public void run() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jtp.setPreferredSize(new Dimension(400, 200));
jtp.addTab("Control", new MyPanel("Channel"));
f.add(jtp, BorderLayout.CENTER);
f.pack();
f.setVisible(true);
}
});
}
private static class MyPanel extends JPanel {
private final JLabel label = new JLabel("", JLabel.LEFT);
private final JTextField text = new JTextField();
public MyPanel(String name) {
this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
label.setText(name);
label.setAlignmentY(JLabel.TOP_ALIGNMENT);
text.setAlignmentY(JTextField.TOP_ALIGNMENT);
this.add(label);
this.add(text);
}
}
}