I have two files, one is Main.java and the second is frame.java.
I'm creating a desktop application so I want to add scrollpane as needed vertically or horizontally in Main.java file.
Frame.java throws the JPanel object which is being catched by Main.java and dynamically loaded into JFrame.
So anyone please tell me, how can I add the scrollpane or scrollbar. Which is best, I don't know. Thank you..
Main.java:
package pack;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
JPanel pn = null;
JFrame mainFrame = null;
frame login = new frame();
mainFrame = new JFrame("Prem");
mainFrame.setLayout(new BorderLayout());
mainFrame.setDefaultCloseOperation(mainFrame.EXIT_ON_CLOSE);
mainFrame.setSize(500,500);
mainFrame.setLocationRelativeTo(null);
pn=login.getLogin();
mainFrame.add(pn,BorderLayout.CENTER);
mainFrame.setVisible(true);
}
public Main() {
super();
}
}
This is second file which throws the panel object from method frame.java
package pack;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.AbstractAction;
import java.awt.*;
import java.awt.event.*;
public class frame {
JPanel pane = null,pane1=null;
JTextField userText=null,passText=null;
JLabel userLabel =null,passLabel=null,errorLabel=null;
JButton submitLogin = null;
public frame()
{
pane = new JPanel();
pane.setLayout(null);
}
public JPanel getLogin()
{
userLabel = new JLabel("UserName");
pane.add(userLabel);
userLabel.setBounds(5,10,100, 30);
userText = new JTextField();
pane.add(userText);
userText.setBounds(110,10,120,30);
passLabel = new JLabel("PassWord");
pane.add(passLabel);
passLabel.setBounds(5,60,100, 30);
passText = new JTextField();
pane.add(passText);
passText.setBounds(110,60,120,30);
errorLabel = new JLabel("");
pane.add(errorLabel);
errorLabel.setBounds(5,150,180,30);
submitLogin = new JButton("Submit");
pane.add(submitLogin);
submitLogin.setBounds(80,110,90,30);
submitLogin.addActionListener(new AbstractAction(){
public void actionPerformed(ActionEvent e)
{
if(submitLogin.getActionCommand() == "Submit")
{
if(userText.getText().isEmpty() || passText.getText().isEmpty())
{
errorLabel.setText("Enter UserName And Password");
}
else
{
//connection
}
}
else
{
System.exit(0);
}
}
});
return pane;
}
}
You have several issues with that code including:
You don't show us in your code where you're trying to use a JScrollPane or even where it's needed. If you show us your attempt to use this, we'll get a much better understanding of your problem.
You are using a null layout and setBounds(...), something you should avoid at almost all costs, and something which absolutely must be avoided if you want to use a JScrollPane, since JScrollPane's do not work well with null layouts. Instead read up on and use layout managers.
You're comparing Strings using the == operator. You don't want to compare Strings using ==. Use the equals(...) or the equalsIgnoreCase(...) method instead. Understand that == checks if the two objects are the same which is not what you're interested in. The methods on the other hand check if the two Strings have the same characters in the same order, and that's what matters here.
You can find links to the Swing tutorials and other Swing resources here: Swing Info
You can find the layout manager tutorial here: Layout Manager Tutorial.
You can learn about "nesting" layouts here.
You can find specific information on how to use JScrollPanes here: JScrollPane Tutorial.
The basic use of them is that you will want to add your scrollable component to the JScrollPane's viewport, and then add the JScrollPane to the GUI. The specifics of how to do this will all depend on your needs, something we don't yet know, but again is very well explained in the tutorials that I've linked to above.
Related
What's wrong? ImageIcon and the frame's size are working properly.
But the JTextField and the JButton aren't.
I need the solution.
import javax.swing.*;
import javax.swing.ImageIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Frame {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setTitle("Alkalmazás");
frame.setVisible(true);
frame.setSize(500,500);
frame.setResizable(false);
JTextField field = new JTextField();
field.setBounds(40,250, 300,35);
JButton button = new JButton(new ImageIcon("table.png"));
button.setBounds(40,400, 250,25);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
tf.setText(""something);
}
});
frame.add(field);
frame.add(button);
}
}
You didn't mention what's "not working properly", but there are a few errors with your code:
Don't call your class Frame, it may confuse you or others about java.awt.Frame, something that may work would be MyFrame
Right now all your class is inside the main method and it's not placed inside the Event Dispatch Thread (EDT), to fix this, create an instance of your class and call a method createAndShowGUI (or whatever you want to name it) inside SwingUtilities.invokeLater()
For Example:
public static void main(String args[]) {
SwingUtilities.invokeLater(new MyFrame()::createAndShowGUI)
}
Or if using Java 7 or lower, use the code inside this answer in point #2.
setVisible(true) should be the last line in your code, otherwise you may find some visual glitches that may be resolved until you move your mouse above your window or something that triggers the call to repaint() of your components.
Instead of calling setSize(...) directly, you should override getPreferredSize(...) of your JPanel and then call pack() on your JFrame, see this question and the answers in it: Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?
You're adding 2 components to the CENTER of BorderLayout, which is a JFrame's default layout manager, there are other layout managers and you can combine them to make complex GUI's.
setBounds(...) might mean that you're using null-layout, which might seem like the easiest way to create complex layouts, however you will find yourself in situations like this one if you take that approach, it's better to let Swing do the calculations for you while you use layout managers. For more, read: Why is it frowned upon to use a null layout in Swing?
With all the above tips now in mind, you may have a code similar to this one:
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class MyFrame {
private JFrame frame;
private JPanel pane;
private JTextField field;
private JButton button;
public static void main(String[] args) {
SwingUtilities.invokeLater(new MyFrame()::createAndShowGUI);
}
private void createAndShowGUI() {
frame = new JFrame("Alkalmazás");
pane = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(100, 100);
}
};
pane.setLayout(new BoxLayout(pane, BoxLayout.PAGE_AXIS));
field = new JTextField(10);
button = new JButton("Click me");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
field.setText("something");
}
});
pane.add(field);
pane.add(button);
frame.add(pane);
frame.setResizable(false);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Now you have an output similar to this one:
What about you want the JTextField to have a more "normal" size? Like this one:
You'll have to embed field inside another JPanel (with FlowLayout (the default layout manager of JPanel)), and then add that second JPanel to pane, I'm not writing the code for that as I'm leaving that as an exercise to you so you learn how to use multiple layout managers
I can't seem to find a solution online for why I'm getting this error on attempted run
I'm working on making a simple test system for a different program when are button press will yield value in a text box. I would like them to be on different lines to make it cleaner, so I looked into layouts. I decided a Box Layout would fit me best. I looked at different examples before attempting this and my code ended up looking like this, (apologies for the messy code)
Update
Got the box layout error to disappear but the code will not center them on the panel/frame. The label and button align left while the textfield becomes very large. I don't need it todo that
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import static javax.swing.BoxLayout.Y_AXIS;
import static javax.swing.SwingConstants.CENTER;
public class button extends JFrame {
static JFrame f;
static JButton b;
static JLabel l;
// main class
public static void main(String[] args)
{
// create a new frame to stor text field and button
f = new JFrame("panel");
BoxLayout layout = new BoxLayout(f, BoxLayout.Y_AXIS);
f.setLayout(layout);
// create a label to display text
l = new JLabel("panel label");
b = new JButton("button1");
JTextField textArea = new JTextField(5);
textArea.setEditable(false);
//textArea.append("Hello World");
// create a panel to add buttons
JPanel p = new JPanel();
// add buttons and textfield to panel
f.add(p);
f.setSize(300, 300);
p.add(l);
p.add(b);
p.setBackground(Color.white);
p.add(textArea);
f.show();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
Random r = new Random();
textArea.setText(String.valueOf(r));
}
});
}
}
Error
Exception in thread "main" java.awt.AWTError: BoxLayout can't be shared
at java.desktop/javax.swing.BoxLayout.checkContainer(BoxLayout.java:461)
at java.desktop/javax.swing.BoxLayout.invalidateLayout(BoxLayout.java:245)
at java.desktop/javax.swing.BoxLayout.addLayoutComponent(BoxLayout.java:278)
at java.desktop/java.awt.Container.addImpl(Container.java:1152)
at java.desktop/java.awt.Container.add(Container.java:1029)
at java.desktop/javax.swing.JFrame.addImpl(JFrame.java:553)
at java.desktop/java.awt.Container.add(Container.java:436)
at button.main(button.java:36)
I would like the three items to all to be stacked one on top of another with a space between them. The order doesn't matter right now.
Swing was first added to the JDK in 1998 and has undergone a lot of changes since. Unfortunately, when you read Web pages about Swing, it is not obvious when that page was last updated. Consequently you may be learning outdated techniques for writing Swing code.
First of all, according to the code you posted, class button does not need to extend class JFrame since you use a static variable as your application's JFrame. Also, JFrame is a top-level container which makes it a special kind of container and not the same kind of continer as a JPanel. You need to set the layout manager for your JPanel and then add the JLabel, JTextField and JButton to that JPanel. And then add the JPanel to the JFrame.
Calling method pack() of class JFrame will automatically set the preferred sizes for the components inside the JFrame. It appears in the code below.
Please also look at Java coding conventions which allows others to more easily read and understand your code. And note that, according to these conventions, I renamed your class from button to Buttons and also because there are already several class in the JDK named Button.
Here is my rewrite of your code...
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.WindowConstants;
public class Buttons implements Runnable {
public void run() {
createAndShowGui();
}
private void createAndShowGui() {
JFrame f = new JFrame("Box");
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel p = new JPanel();
BoxLayout layout = new BoxLayout(p, BoxLayout.Y_AXIS);
p.setLayout(layout);
JLabel l = new JLabel("panel label");
JTextField textField = new JTextField(5);
JButton b = new JButton("button1");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
Random r = new Random();
textField.setText(String.valueOf(r.nextBoolean()));
}
});
p.add(l);
p.add(textField);
p.add(b);
f.add(p);
f.pack();
f.setLocationByPlatform(true);
f.setVisible(true);
}
public static void main(String[] args) {
Buttons instance = new Buttons();
EventQueue.invokeLater(instance);
}
}
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.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class SideNotes {
public static JPanel panel = new JPanel();
private List<String> notes = new ArrayList<String>();
private static JButton add = new JButton("Add note");
public SideNotes() {
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.add(add);
loadNotes();
add.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
addNote();
}
});
}
public void addNote() {
String note = JOptionPane.showInputDialog("Enter note: ", null);
notes.add(note);
JLabel label = new JLabel(note);
panel.add(label);
panel.revalidate();
panel.repaint();
}
private void loadNotes() {
for (int i = 0; i < notes.size(); i++) {
JCheckBox jcb = new JCheckBox(notes.get(i), false);
panel.add(jcb);
panel.revalidate();
panel.repaint();
}
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(200, 400);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.add(add);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
new SideNotes();
}
}
Why isn't my JCheckBox showing up? The text shows up but not the actual box. What's the deal?
I have edited my post to contain all of my code in case that helps solve the issue.
needmoretextneedmoretextneedmoretextneedmoretextneedmoretextneedmoretextneedmoretext
Possible reasons:
panel has not been added to GUI
panel has been added but for some reason is not visible.
panel is too small to show the child component. This can happen for instance if you set a component's size or preferredSize or if you place it in a FlowLayout-using container without thought.
panel uses null layout.
panel's layout manager is not one that easily accepts a new component -- think GroupLayout for this one.
There are other unspecified layout manager problems going on. Do you call pack() on your GUI? Do you use null layout or absolute positioning anywhere? Do you need to put panel in a JScrollPane?
Consider creating and posting an sscce for better help.
Edit
Your posted code doesn't ever add any JCheckBoxes to the JPanel, just JLabels. To prove this is so, click on the labels and you'll see that they don't respond to clicks.
Your code grossly over-uses static fields. Get rid of all static modifiers on all variables. They should all be instance variables. The only static anything in your code above should be the main method, and that's it. If this causes errors, then fix the errors, but not by making fields static.
Give your SideNotes class a method, getPanel() that returns the panel field.
Create a SideNotes instance in the beginning of your main method. Then call the above method on the instance to get the JPanel for the JFrame. i.e., frame.add(sideNotes.getPanel());.
Don't add JLabels to your GUI (I've no idea why you're doing this). Add JCheckBoxes in the actionPerformed method.
Every time you press the button, a new Note (JLabel) is added to the panel. But you never call loadNotes() after adding a new Note. So the JLabel is added but not its respective JCheckBox as intended.
Besides of this I'd suggest you make this change:
public void addNote() {
String note = JOptionPane.showInputDialog("Enter note: ", null);
if(notes != null) {
notes.add(note);
JLabel label = new JLabel(note);
panel.add(label);
panel.add(new JCheckBox(note, false));
panel.revalidate();
panel.repaint();
}
}
So you don't need to call loadNotes() and update the GUI just once.
My issue is, rather than the elements being on top of each other neatly, there are huge blocks of space unnecessarily in between each element of the gui that I use in the program.
I'm trying to have it like this:
label
textfield, button
textarea
But instead it's coming out like
label
(blotch of space)
textfield, button
(blotch of space)
textarea
when I run it. Any help is appreciated, I've really been trying to figure it out by myself.
package guiprojj;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Map;
import javax.swing.*;
import com.eclipsesource.json.JsonObject;
import com.google.gson.JsonParser;
import com.json.parsers.JSONParser;
import com.json.parsers.JsonParserFactory;
public class gui {
public static void main(String[] args)
{
JFrame maingui = new JFrame("Gui");
JButton enter = new JButton("Enter");
final JTextArea movieinfo = new JTextArea(5,20);
final JTextField movietext = new JTextField(16);
final JScrollPane scrolll = new JScrollPane(movieinfo);
final JLabel titlee = new JLabel("Enter movie name here:");
JPanel pangui = new JPanel();
JPanel pangui2 = new JPanel();
maingui.setLayout(new GridLayout(3, 0));
maingui.add(titlee);
pangui.add(movietext);
pangui.add(enter);
pangui2.add(scrolll);
//scrolll.add(movieinfo);
//pangui.add(movieinfo);
maingui.setResizable(false);
maingui.setVisible(true);
movieinfo.setLineWrap(true);
movieinfo.setWrapStyleWord(true);
movieinfo.setEditable(false);
maingui.add(pangui);
maingui.add(pangui2);
scrolll.getPreferredSize();
//pangui.setPreferredSize(new Dimension(300, 150));
//pangui.add(scrolll, BorderLayout.CENTER);
//movieinfo.add(scrolll);
maingui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
maingui.pack();
enter.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
System.out.println(Test.getMovieInfo(movietext.getText()));
JsonParserFactory factory=JsonParserFactory.getInstance();
JSONParser parser=factory.newJsonParser();
Map jsonData=parser.parseJson(Test.getMovieInfo(movietext.getText()));
String Title = (String)jsonData.get("Title");
String Year = (String)jsonData.get("Year");
String Plot = (String)jsonData.get("Plot");
movieinfo.setText("Title: "+Title+"\nYear: "+ Year +"\nPlot: "+Plot);
}
});
}
}
This is how GridLayout works: all grid cells are the same size, probably the largest preferredSize of its components. Better to do what I suggested in my last answer: nesting BorderLayout using JPanels.
You need to use a layout manager that works the way you expect it to. There are several managers included with Java and I recommend you start here:
http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html
This will give you a good visual introduction to the various layout managers and should give you the foundation you need to pick the right one.
if u need to put them separately or with variable space , just use GridBag Layout or use absolute layout i.e. no layout, with manual positioning
it would be easy using for loop for aligning in absolute layout (using setBounds(x,y,width,height)