The following problem boggled my mind, so I came here for some help.
After experimenting I ended up with this block of code:
JTextArea chatPanel = null;
JScrollPane scrollPanel = null;
if(chatPanel == null)
{
chatPanel = new JTextArea("derp");
chatPanel.setEditable(false);
chatPanel.setForeground(new Color(10,191,26));
chatPanel.setOpaque(false);
scrollPanel = new JScrollPane(chatPanel);
scrollPanel.setOpaque(false);
scrollPanel.getViewport().setOpaque(false);
scrollPanel.setBorder(BorderFactory.createEmptyBorder());
}
//## marked area ##
scrollPanel.setBounds(9,596,435,138);
pane.add(scrollPanel);
The result? Nothing shows up. The text area with "derp" in it I expected is not there, just an empty scroll panel. Now, if I go to the ## marked area ## and replace it with this:
chatPanel.append("Hello.");
the chatPanel shows up fine in the scrollPanel, with its text being "derpHello.". Any ideas as per what's going on?
For the record, pane is a simple container with a null layout that otherwise displays eveyrthing fine. Declaration, just for the record:
Container pane = getContentPane()
pane.setLayout(null);
I have no problem with the following code, I can see the "derp" in green just fine:
import java.awt.Color;
import java.awt.Container;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class TestTextArea {
private void initUI() {
JFrame frame = new JFrame("test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTextArea chatPanel = null;
JScrollPane scrollPanel = null;
Container pane = frame.getContentPane();
pane.setLayout(null);
if (chatPanel == null) {
chatPanel = new JTextArea("derp");
chatPanel.setEditable(false);
chatPanel.setForeground(new Color(10, 191, 26));
chatPanel.setOpaque(false);
scrollPanel = new JScrollPane(chatPanel);
scrollPanel.setOpaque(false);
scrollPanel.getViewport().setOpaque(false);
scrollPanel.setBorder(BorderFactory.createEmptyBorder());
}
// ## marked area ##
scrollPanel.setBounds(9, 596, 435, 138);
pane.add(scrollPanel);
frame.validate();
frame.setSize(600, 800);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestTextArea().initUI();
}
});
}
}
Now, I would really advise you to use an appropriate LayoutManager instead of that null layout. That would allow you to use pack() and revalidate() and have a much simpler and more maintainable code.
There must be something else that your code does not illustrate for now. Try to put an SSCCE.
There is nothing in your JTextArea to display as you initialize it with the empty String. When you append something to it, there is effectively text inside.
Note that your JScrollPane will never try to resize your component inside (why else would it allow you to scroll?). Therefore, you will have to set a dimension on your JTextArea.
EDIT (after your code correction): I can see "derp" just fine with following code.
public class TextTest extends JFrame {
public TextTest () {
JPanel pane = new JPanel();
JTextArea chatPanel = null;
JScrollPane scrollPanel = null;
if(chatPanel == null)
{
chatPanel = new JTextArea("derp");
chatPanel.setEditable(false);
chatPanel.setForeground(new Color(10,191,26));
chatPanel.setOpaque(false);
scrollPanel = new JScrollPane(chatPanel);
scrollPanel.setOpaque(false);
scrollPanel.getViewport().setOpaque(false);
scrollPanel.setBorder(BorderFactory.createEmptyBorder());
}
//## marked area ##
scrollPanel.setBounds(9,596,435,138);
pane.add(scrollPanel);
setContentPane(pane);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new TextTest();
}
}
Related
This is the add(main) version
This is the add(scroll) version
Im trying to get a window full of lables and make it scrollable, this is my code for that purpose:
public class JobHistoryListScreen extends JFrame implements View
{
#Override
public void showScreen()
{
setSize(800, 800);
setLayout(new BorderLayout());
setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel main = new JPanel();
main.setSize(500,500);
JScrollPane scroll = new JScrollPane(main,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scroll.setSize(500,500);
//Font
//Font david50 = new Font("David", Font.BOLD, 50);
for(int i=0; i<1000; i++)
{
JLabel empty = new JLabel("No jobs to display!");
empty.setBounds(0,i+250,400,100);
empty.setFont(david50);
main.add(empty);
}
add(main);
setVisible(true);
}
public static void main(String[] args) {
JobHistoryListScreen v = new JobHistoryListScreen();
v.showScreen();
}
}
For some reason the window gets filled with the labels but is not scrollable at all.
Learn about layout managers. Refer to Laying Out Components Within a Container. Default for JPanel is FlowLayout and because the JPanel is inside a JScrollPanel, the labels will not wrap. And since you set the horizontal scroll bar policy to NEVER, there is no horizontal scroll bar and hence you cannot scroll horizontally. Try using BoxLayout to display all the labels one under the other. Alternatively you could use a GridLayout with 0 (zero) rows and 1 (one) column. Refer to the tutorial for more details.
EDIT
Here is my modified version of your code. Explanatory notes appear after the code.
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.WindowConstants;
public class JobHistoryListScreen implements Runnable {
private JFrame frame;
#Override // java.lang.Runnable
public void run() {
showScreen();
}
public void showScreen() {
frame = new JFrame("Jobs");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel main = new JPanel(new GridLayout(0, 1));
JScrollPane scroll = new JScrollPane(main,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scroll.setPreferredSize(new Dimension(500, 500));
Font david50 = new Font("David", Font.BOLD, 50);
for(int i=0; i<1000; i++) {
JLabel empty = new JLabel("No jobs to display!");
empty.setFont(david50);
main.add(empty);
}
frame.add(scroll);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
JobHistoryListScreen v = new JobHistoryListScreen();
// Launch Event Dispatch Thread (EDT)
EventQueue.invokeLater(v);
}
}
I don't know what interface View is so I removed that part.
No need to extend class JFrame.
No need to explicitly call setSize() on JFrame. Better to call pack().
Default content pane for JFrame is JPanel and default layout manager for that JPanel is BorderLayout so no need to explicitly set.
No need to call setSize() on JPanel.
Call setPreferredSize() rather than setSize() on JScrollPane.
Add the JScrollPane to the JFrame and not the JPanel.
No need to call setBounds() because GridLayout handles this.
Explicitly launch EDT (Event Dispatch Thread) by calling invokeLater().
Here is a screen capture of the running app. Note the vertical scroll bar.
I am having trouble implementing JLabel with JFrame. The program needs to show either "Hello" or "World" in the center of the screen when the button "study" is pressed. Also with this being a flashcard program, when study is pressed a word is placed on the middle of the screen and the program is suppose to read from the text field for the user input and print whether it is right or wrong. The problem is that the program is reading the text field after study is pressed so it is printing false before the user can input a answer.
Can someone briefly explain why this is not working and what I can do to fix this issue?
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JButton;
public class NoteCardGUI implements ActionListener {
public static JFrame frame;
public static JPanel panel;
public static JLabel label;
private NoteCard ex;
private JButton study;
public static Box box1 = new Box(), box2 = new Box(), box3 = new Box();
public NoteCardGUI() {
ex = new NoteCard("Hello", "World");
frame = new JFrame("Flash Card");
panel = new JPanel();
study = new JButton("Study");
study.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String resp = NoteCard.getResponse(ex);
String chal = NoteCard.getChallenge(ex);
String a = text.getText();
label = new JLabel(chal, label.CENTER);
label.setAlignmentX(0);
label.setAlignmentY(0);
frame.add(label, BorderLayout.SOUTH);
frame.revalidate();
if(resp.compareTo(a) == 0)
{
label = new JLabel("Correct!");
}
label = new JLabel("Incorrect");
}
});
panel.add(study);
frame.add(panel);
frame.setSize(500, 500);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
new NoteCardGUI();
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
}
You are adding the label to your frame, but you already have added a JPanel on top of the frame. The solution is to add the label to the panel instead of the frame.
So change: frame.add(label); to panel.add(label);
By default, a JFrame (or rather, its content pane) has BorderLayout. This means that if you add components to it without specifying a constraint, they will be added at the CENTER. But you can't add more than one element at any of the BorderLayout's regions.
So in order for this to work, you need to add the label somewhere else other than the center, or have the panel added with some other, explicit region.
So if you change the add, for example, to:
frame.add(label, BorderLayout.NORTH);
It will work - but you must not forget to also add:
frame.revalidate();
Whenever you add components to your GUI, you should call this when you've added them all, in order for it to rebuild the hierarchy of components as needed.
Another option would be to change the layout manager of the Frame, or to add to the panel.
I've been having some (very annoying) trouble with these scripts that I've created.
Sburb.java
import java.awt.Color;
import javax.swing.*;
public class Sburb
{
public static void main (String[] args)
{
JFrame frame = new JFrame ("Welcome to Sburb");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
spirograph page = new spirograph();
progressbar bar = new progressbar();
frame.getContentPane().add(page);
frame.getContentPane().add(bar);
frame.pack();
frame.setVisible(true);
frame.setResizable(true);
}
}
progressbar.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class progressbar extends JPanel
{
JProgressBar current;
JTextArea out;
JButton find;
Thread runner;
int num = 1;
progressbar()
{
super();
//setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel pane = new JPanel();
pane.setLayout(new FlowLayout());
current = new JProgressBar(0, 2000);
current.setStringPainted(false);
pane.add(current);
//setContentPane(pane);
}
public void iterate() {
while (num < 2000) {
current.setValue(num);
try {
Thread.sleep(300);
} catch (InterruptedException e) { }
num += 5;
}
}
// public static void main(String[] arguments) {
// progressbar frame = new progressbar();
// frame.pack();
// frame.setVisible(true);
// frame.iterate();
// }
}
spirograph.java
import java.awt.Color;
import java.awt.FlowLayout;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class spirograph extends JPanel
{
private ImageIcon image;
private JLabel label;
private JLabel frame = new JLabel();
private JPanel panel = new JPanel();
spirograph()
{
this.setOpaque(true);
this.setBackground(Color.BLACK);
setLayout(new FlowLayout());
image = new ImageIcon(getClass().getResource("Gate.gif"));
label = new JLabel(image);
add(label);
progressbar bar = new progressbar();
}
}
I'm trying to call the file "progressbar" to the Sburb file but when I do, it gives me just the simple JFrame of this (not fixed):
http://imgur.com/1aAmPwJ
And when I get rid of the "frame.getContentPane().add(bar);" in Sburb.java, it gives me this (fixed, kind-of):
http://imgur.com/15aGtT2
How do I fix this? I've looked everywhere and yet I still can't figure it out! I also can't seem to figure out how to align the bar directly below the gif.
frame.getContentPane().add(page);
frame.getContentPane().add(bar);
The content pane of a JFrame is a set to a BorderLayout which can only accept one component in any one of the border layout constraints. Given no constraints were supplied here, the JRE will try to put them both in the CENTER.
For this, and a variety of other reasons, I would advise to ignore the existing content pane, arrange the entire GUI (as many panels as it consists of) into another panel (let's call it ui) then call
frame.setContentPane(ui);
I've a window and since I dinamically change it's children (sometimes I swap JPanels), I found no other solution than calling pack() on the window to get the new element displayed. Otherwise it will show up only if I resize manually the window.
The problem with this is that the if the window is maximized, after pack() it won't be anymore, which is not what I could give to the client.
Any clues?
First of all, I hope that you're using CardLayout for panel swapping, since this functionality is built into that particular layout manager. And typically, you'll want to invoke validate/revalidate and repaint on the container to refresh the display.
See also:
How to Use CardLayout
If you really have to:
int state = frame.getExtendedState();
frame.pack();
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
... Otherwise #mre's solution is (much) better! :)
I got the same problem as you and for me I m satisfied with my solution I share it may be it help you on your context
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
*
* #author Housseyn
*/
public class JPanelTools {
public static final void ShowPanel(JPanel target, JPanel object) {
target.removeAll();
Dimension size = object.getSize();
size.setSize(size.width, target.getHeight());
target.setSize(object.getSize());
GridBagLayout gridBagLayout = new GridBagLayout();
target.setLayout(gridBagLayout);
GridBagConstraints gbc = new GridBagConstraints(target.getX(),
target.getY(),
target.getWidth(),
target.getHeight(),
0, 0,
GridBagConstraints.ABOVE_BASELINE,
0,
new Insets(5, 5, 5, 5),
0, 0);
target.add(object, gbc);
target.invalidate();
target.revalidate();
target.validate();
target.repaint();
target.show();
object.validate();
object.repaint();
object.show();
Container Frame = target.getParent();
Container Current = target.getParent();
while ((Current != null)) {
System.out.println("current =" + Current.getClass().getName());
Frame = Current;
Current = Current.getParent();
}
System.out.println("frame " + Frame.getClass().getName());
if (Frame != null) {
System.out.println("pack");
JFrame MyFrame = (JFrame) Frame;
int extendedState = MyFrame.getExtendedState();
if (extendedState != JFrame.MAXIMIZED_BOTH) {
MyFrame.pack();
MyFrame.setExtendedState(extendedState);
}
}
}
}
I designed an empty panel on my main Frame and in a button I call this
MyDesignedPanel myPanel = new MyDesignedPanel();
JPanelTools.ShowPanel(JemptyPanel, myPanel);
that works perfectly for me
That my new way of handling this issue :
public static void showForms(JFrame frame,JPanel[] jPanels){
for (JPanel jPanel : jPanels) {
showForms(frame, jPanel,false);
}
int extendedState = frame.getExtendedState();
if (extendedState==JFrame.MAXIMIZED_BOTH) {
return;
}
frame.pack();
}
public static void showForms(JFrame frame, JPanel jPanel, boolean doPack) {
jPanel.setVisible(true);
if (doPack) {
int extendedState = frame.getExtendedState();
if (extendedState==JFrame.MAXIMIZED_BOTH) {
return;
}
frame.pack();
}
}
public static void hideForms(JFrame frame, JPanel[] jPanel) {
for (JPanel panel : jPanel) {
hideForms(frame, panel, false);
}
int extendedState = frame.getExtendedState();
if (extendedState==JFrame.MAXIMIZED_BOTH) {
return;
}
frame.pack();
}
public static void hideForms(JFrame frame, JPanel jPanel, boolean doPack) {
jPanel.setVisible(false);
if (doPack) {
int extendedState = frame.getExtendedState();
if (extendedState==JFrame.MAXIMIZED_BOTH) {
return;
}
frame.pack();
}
}
I m using this methods to hide and show jpanels on my jframe.
sample on a button code
JFrameTools.showForms(this,searchPanel,false);
JFrameTools.showForms(this,insertingPanel,true);
JFrameTools.showForms(this,new jPanel[]{insertingPanel,searchPanel,printingPanel});
the same for the hiding.
I'm trying to create a simple JList with a scrollbar, and therefore i need to have the JList within a JScrollPane. So far, so good. However, for some reason i can't resize/position the JScrollPane!? It sounds logic that everything inside it should stretch to 100%, so if i set the JScrollPane to be 300px wide, the elements inside will be as well. Is that correct?
While you're at it, please critisize and give me hints if i should change something or optimize it.
Anyhow, here's the code:
package train;
import java.awt.*;
import javax.swing.*;
public class GUI {
private DefaultListModel loggerContent = new DefaultListModel();
private JList logger = new JList(loggerContent);
GUI() {
JFrame mainFrame = new JFrame("title");
this.addToLog("testing testing");
this.addToLog("another test");
// Create all elements
logger = new JList(loggerContent);
JScrollPane logWrapper = new JScrollPane(logger);
logWrapper.setBounds(10, 10, 20, 50);
// Add all elements
mainFrame.add(logWrapper);
// Show everything
mainFrame.setSize(new Dimension(600, 500));
mainFrame.setVisible(true);
}
public void addToLog(String inputString) {
int size = logger.getModel().getSize();
loggerContent.add(size, inputString);
}
}
Thanks in advance,
qwerty
EDIT: Here's a screenshot of it running: http://i.stack.imgur.com/sLGgQ.png
The setVisibleRowCount() method of JList is particularly convenient for this, as suggested in the relevant tutorial. ListDemo is a good example.
Addendum:
please critisize and give me hints…
Well, since you ask: Don't invoke public methods in the constructor; make them private or invoke them after the constructor finishes. There's no need to find the last index for add(), when addElement() is available. Also, be sure to construct your GUI on the event dispatch thread .
import java.awt.*;
import javax.swing.*;
/** #see http://stackoverflow.com/questions/5422160 */
public class ListPanel extends JPanel {
private DefaultListModel model = new DefaultListModel();
private JList list = new JList(model);
ListPanel() {
list.setVisibleRowCount(5);
}
public void append(String inputString) {
model.addElement(inputString);
}
private void init() {
for (int i = 0; i < 10; i++) {
this.append("String " + String.valueOf(i));
}
JFrame mainFrame = new JFrame("GUI");
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JScrollPane jsp = new JScrollPane(list);
mainFrame.add(jsp);
mainFrame.pack();
mainFrame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new ListPanel().init();
}
});
}
}
The bounds & size of a component are generally ignored over that of it's preferred size and the constraints of the layout being used by the container.
To solve this problem, learn how to use layouts & apply them appropriately.
Try to put your JScrollPane inside a JPanel and add the panel to the frame.
JPanel panel = new JPanel();
panel.add (logWrapper);
mainFrame.add(panel);
Then set the bounds of the panel instead of the JScrollpane
panel.setBounds(10, 10, 20, 50);
The probles is that Swing uses layout managers to control child bounds property. Adding a JScrollpane directly to the main frame, doesn't allow you to choose right bounds properly.