I want to create two non-editable textboxes (each will contain only one line) with a fixed size, but I want them to be scrollable (horizontally only) because I know the text they will contain will be very long. I want them to be below the two buttons I define below, and I want each textbox on their own row.
Problem is, everything shows up and buttons work as expected, but the textbox won't scroll, although I can somehow drag and select the rest of the text in the box that isn't visible. I don't know if labels are scrollable, would they be a better option?
Code:
public static void main(String[] args)
{
JFrame win = new JFrame("Window");
win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
win.setSize(400, 300);
GridBagConstraints c = new GridBagConstraints();
win.setLayout( new GridBagLayout() );
JTextArea master = new JTextArea(1,1);
JTextArea vendor = new JTextArea(1,1);
master.setEditable(false);
vendor.setEditable(false);
master.setPreferredSize( new Dimension(100,20) );
vendor.setPreferredSize( new Dimension(100,20) );
master.setText(/*some really long string*/);
vendor.setText(/*some really long string*/);
JScrollPane mPane = new JScrollPane(master, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
JScrollPane vPane = new JScrollPane(vendor, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
mPane.getHorizontalScrollBar().isVisible();
vPane.getHorizontalScrollBar().isVisible();
JButton one = new JButton("Select");
ActionListener select = new SelectButton(master, vendor);
one.addActionListener(select);
JButton two = new JButton("Run");
c.gridx = 0;
c.gridy = 0;
win.add(one, c);
c.gridx = 1;
c.gridy = 0;
win.add(two, c);
c.gridx = 0;
c.gridy = 1;
win.add(master, c);
win.add(mPane, c);
c.gridx = 0;
c.gridy = 2;
win.add(vendor, c);
win.add(vPane, c);
win.setLocationRelativeTo(null);
win.setVisible(true);
return;
}
Don't, ever, use setPreferredSize! This is overriding the information that the JScrollPane needs in order to make decisions about how the components should be scrolled. See Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing? for more details. Instead use the JTextArea(int, int) constructor to provide hints to the JScrollPane, for example JTextArea master = new JTextArea(1, 20);. Any text longer then 20 characters will cause the JScrollPane to display the horizontal scroll bar...
Don't add both the JTextArea AND the JScrollPane to the container. Adding the JTextArea automatically removes it from the JScrollPane, which isn't what you want.
Use GridBagConstaints#gridwidth to control the number of columns a component might expand across to help fix your layout...
For example...
c.gridx = 0;
c.gridy = 1;
c.gridwidth = GridBagConstraints.REMAINDER;
win.add(mPane, c);
c.gridx = 0;
c.gridy = 2;
win.add(vPane, c);
I'm hoping this is a really simple example, if not, you should always make sure that your UI is created and modified from within the context of the EDT. See Initial Threads for more details
Related
In my application I'm using a JSplitPane to devide the GUI into two sides. Every side will contain some components, one of them being a JEditorPane. The components are placed horizontally next to each other. All components should have a fixed size exept for the JEditorPanel. This should take all the available horizontal space. So, if the divider of the splitPane is moved the JEditorPane should change its width. My current implementation works fine if the divider is moved in a direction where the with of the JSplitPane increases. However, it is not possible to move the divider in the other direction. Below is a minimalistic example of my problem. In the example I'm using a GridbagLayout. However, this problem remains also for other layout manager. Also interesting is that this problem seems to be unique for the JEditorPane. The implementation works fine when the JEditorPane is replaced, for example by a JButton.
Here is my code:
import javax.swing.*;
import java.awt.*;
public class Test {
public static void main(String[] args) {
JFrame f = new JFrame();
f.setSize(500, 500);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panelRight = new JPanel();
JPanel panelLeft = new JPanel();
panelRight.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
JButton b = new JButton("button");
c.gridx = 1;
c.gridy = 0;
panelRight.add(b, c);
JEditorPane ep = new JEditorPane();
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 0;
c.weightx = 1;
panelRight.add(ep, c);
JSplitPane sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, panelLeft, panelRight);
sp.setResizeWeight(0.5);
f.add(sp);
f.setVisible(true);
}
}
Does anyone have an idea why this is happending and/or how to fix it?
I want to make the text automatically as wide as the window. I tried using text.setSize(window.getWidth(),20) and text.setBounds(window.getWidth(),20), (where text is JTextfield), but the only way that seems to work is: static JTextField text = new JTextField(int numberOfColumns); I'm using GridBag layout.
EDIT: I have edited example according to GridBagLayout.
Use layout manager. It will automatically expands component according to window.
For example;
Jpanel panel = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridwidth = GridBagConstraints.REMAINDER;
panel.add(textfield,c);
I've been trying to get a scrollable JTextArea to appear to the right of a JList where the JTextArea takes up most of the space but leaves a good portion for the JList (3/4 of the frame for the JTextArea, 1/4 for the JList). The problem is that the weights of the constraints seem to be ignored when LineWrap on the JTextArea is set to true.
Without line wrap, the JTextArea takes up about 3/4 of the frame and the JList takes up the other 1/4, which is what I want. But when line wrapping is turned on, the JTextArea attempts to take up as much space as possible and crushes the JList down to the width of the strings it contains. The interesting thing is that this only appears to happen once you resize the window (looks fine initially), and if you type anything into the JTextArea, it slowly expands, pushing the JList back. This has been confusing me to say the least.
I made a screenshot of what it looks like without line wrapping and with line wrapping after resizing the window:
Here's some example code showing you what I mean. Remove the line wrap statements and it'll look fine, but keep them there and you'll see that upon resizing, the JList is squished.
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.*
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
JPanel panel = new JPanel(new GridBagLayout());
JTextArea area = new JTextArea();
DefaultListModel<String> model = new DefaultListModel<>();
JList<String> list = new JList<String>(model);
JScrollPane scroll = new JScrollPane(area,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
for (int i = 0; i < 5; i++)
model.addElement("Example" + i);
area.setLineWrap(true);
area.setWrapStyleWord(true);
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.fill = GridBagConstraints.BOTH;
c.weighty = 1;
c.weightx = 0.3;
panel.add(scroll, c);
c = new GridBagConstraints();
c.gridx = 1;
c.fill = GridBagConstraints.BOTH;
c.weighty = 1;
c.weightx = 0.1;
panel.add(list, c);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 300);
frame.setVisible(true);
}
}
You can use ipadx to define minimal possible width
c.weightx = 0.1;
c.ipadx=desiredPixelsWidthForTheList;
panel.add(list, c);
UPDATE
Also you can place both in a JSplitPane and define desired proportions.
The short answer is that the text area gets more width than you want because its preferred width is much larger than that of the list.
Keep in mind that weightx doesn't determine what percentage of space a component will occupy but the proportional amount of space that's added to or taken away from the component's size. In this case, for example, the "extra" space is the difference between the frame's width (or more accurately, its content pane's width) which you explicitly set to 500 and the combined widths of the text area and the list. In other words, both the scroll pane / text area and the list will be displayed at their preferred sizes PLUS 75% of the left-over space for the text area and 25% for the list. Again, since the text area's preferred size is large to begin with, it occupies a bigger portion of the screen than what you want.
As a couple of people have already pointed out, a simple way to get the results you want is to explicitly specify the number of rows and columns for the text area. On the other hand, you should avoid explicitly setting a size, preferred or otherwise as discussed in questions like this.
As far as the mysteriously shrinking list goes, I suspect that's a bug in GridBagLayout. It seems to ignore the maximum size of the JList initially but then respects it when it lays out the components as a result of the frame resizing, which is why it suddenly shrinks and then never gets larger again. That's not normally an issue because like JTextArea, a JList is normally contained within a scroll pane, which is something you should probably also consider doing.
try using .setPreferredSize() to components
I have modified your code. Just specified the size of textarea and list like this
list.setPreferredSize(new Dimension(frame.getWidth()/4, frame.getHeight()));
area.setPreferredSize(new Dimension(frame.getWidth()*(3/4), frame.getHeight()));
check the full code below:
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
JPanel panel = new JPanel(new GridBagLayout());
JTextArea area = new JTextArea();
DefaultListModel model = new DefaultListModel();
JList list = new JList(model);
JScrollPane scroll = new JScrollPane(area,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
for (int i = 0; i < 5; i++)
model.addElement("Example" + i);
frame.setSize(500, 300);
list.setPreferredSize(new Dimension(frame.getWidth()/4, frame.getHeight()));
area.setPreferredSize(new Dimension(frame.getWidth()*(3/4), frame.getHeight()));
area.setLineWrap(true);
area.setWrapStyleWord(true);
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.fill = GridBagConstraints.BOTH;
c.weighty = 1;
c.weightx = 0.3;
panel.add(scroll, c);
c = new GridBagConstraints();
c.gridx = 1;
c.fill = GridBagConstraints.BOTH;
c.weighty = 1;
c.weightx = 0.1;
panel.add(list, c);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
Im currently having trouble Displaying both labels ie text buttons etc and shapes in jframe at same time. What is happening is only the shapes display when i run it.
Can someone tell me how to enable both to be displayed at the same time.
Thanks in advance
Below is some of the code for the labels which is in main class the shapes code is in a
separate class:
JLabel label1 = new JLabel (" some text wont display\n for some reason");
c.gridx = 0;
c.gridy = 0;
panel.add(label1,c);
JButton button1 = new JButton ("4");
c.gridx = 15;
c.gridy = 0;
panel.add(button1,c);
//now to call from the shapes class to have a couple of shapes.
GuiDog object= new GuiDog();
frame.add(object);
object.drawing();
}
You seem to have forgotten to add panel to the frame. The code should work fine after adding it.
Hope this helps.
I'm having an issue with resizing of JTextArea in java.swing. The problem is that once the current line is finished (so for example if i keep pressing space) - it doesn't go to the second line - it just keeps on going. Same thing when i press enter - it stretches out the box vertically. How do I prevent this? I'm using GridBagLayout.
JTextArea MainText = new JTextArea();
MainText.setFont(new Font("Arial", Font.PLAIN, 16));
MainText.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED));
c.fill = GridBagConstraints.BOTH;
c.insets = new Insets (10, 10, 10, 10);
c.gridx = 0;
c.gridy = 2;
c.weightx = 1.0;
c.weighty = 1.0;
c.gridwidth = 3;
c.gridheight = 1;
panel.add(MainText, c);
Set the lineWrap and wrapStyleWord properties of the JTextArea
JTextArea MainText = new JTextArea();
MainText.setLineWrap(true);
MainText.setWrapStyleWord(true);
Take a look at How to use Text Areas for more details
You might also find having a read through Code Conventions for the Java Programming Language of some use
Unless you really don't want to, I would also suggest adding the JTextArea into a JScrollPane instead of adding it directly to the conatiner
panel.add(new JScrollPane(MainText), c);
This will prevent the JTextArea from wanting to grow as more text is added to it (unless that's what you're going for)
To get your JTextAreas to wrap lines on words appropriately, use: mainText.setWrapStyleWord(true) and mainText.setLineWrap(true)
Most important though, get very familiar with using the Java API as it will likely answer 90% of similar questions:
JTextArea API