Adding textfields to jframe using graphics2d - java

public class Contact {
int x0,x1,y2=1500,x3=1500,a=0;
JFrame jf;
private JTextField name = new JTextField();
private JTextField phone;
private JButton start;
boolean clicked=false;
static Dimension dim=Toolkit.getDefaultToolkit().getScreenSize();
static int w=(int)dim.getWidth(); static int h=(int)dim.getHeight();
IntroInner d=new IntroInner(); int c;
public Contact() {
}
public void build() throws Exception{
jf=new JFrame("THE COUNTRY CLUB");
jf.getContentPane().add(d);
jf.setSize(w,h);
jf.setVisible(true);
jf.setAlwaysOnTop(true);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public class IntroInner extends JPanel{
public void paintComponent(Graphics g1){
Graphics2D g=(Graphics2D) g1;
FontMetrics metrics = g.getFontMetrics();
int xpos=(int)Toolkit.getDefaultToolkit().getScreenSize().getWidth()/2-215;
setFont(new Font("serif",Font.ITALIC,40));
g.setColor(Color.black);
g.fillRect(0,0,this.getWidth(),this.getHeight());
Image im1=new ImageIcon("Images/bg.jpg").getImage();
g.drawImage(im1,0,0,this);
//g.rotate(a);
Image im=new ImageIcon("Images/logo.png").getImage();
g.drawImage(im,xpos,50,this);
g.setColor(Color.white);
g.drawString("Please Enter Your Details",400,400);
g.drawString("Name:",400,475);
g.drawString("Contact No:",400,550);
}
}
public static void main(String[] args) throws Exception{
new Contact().build();
}
}
I reffered alot about implementing textfield to java frame using graphics2d in java. But didn't get any useful opinion. I have found something here in stackoverflow also. But that too didn't helped me. Can anybody help me in this. The expected output of this program isgiven below: Thanks in advance.

OK, so you probably need to take a step back and see the two aspects here:
One aspect is that you can directly draw on a Graphics2D object, printing strings, draw lines, fill rectangles, etc... While this can be very interesting in some situations (if you want to perform very custom drawings, for example), this is a very low level approach. You're in charge of doing a lot of things. If you would consider handling a text field, this would mean that you would have to draw a background, a border, a string as it get typed, make a blinking caret, etc... This can easily become very cumbersome and tedious to maintain
The other aspect is that Swing provides a bunch of component which does already all the tedious work I just talked about. While it cannot handle all cases, simple cases such as labels, textfield, images, etc... already have a built-in implementation which basically avoids you the cumbersome work to do it yourself. The only thing left for you is to explain how and where you want your components to appear. This is where LayoutManager's come into play.
Here is a small example (amongst many other) which shows you the gist of doing such thing:
import java.awt.BorderLayout;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class BasicSwingTest {
protected void initUI() throws MalformedURLException {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel image = new JLabel(new ImageIcon(new URL("http://upload.wikimedia.org/wikipedia/commons/thumb/4/45/Duke3D.png/220px-Duke3D.png")));
frame.setLayout(new BorderLayout());
frame.add(image, BorderLayout.WEST);
JPanel mainPanel = new JPanel(new GridBagLayout());
JPanel panel = new JPanel(new GridLayout(0, 2));
panel.add(new JLabel("Name: "));
JTextField name = new JTextField(20);
panel.add(name);
panel.add(new JLabel("Contact no: "));
JTextField contactNumber = new JTextField(15);
panel.add(contactNumber);
panel.setBorder(BorderFactory.createTitledBorder("Enter your details"));
mainPanel.add(panel);
frame.add(mainPanel);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
new BasicSwingTest().initUI();
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
});
}
}
And the outcome:
Here is a second example (looking a bit more like your image, although it needs a few tweaks):
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class BasicSwingTest2 {
private static final Font FONT = new Font("Times New Roman", Font.PLAIN, 18);
protected void initUI() throws MalformedURLException {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
JLabel contentPane = new JLabel(new ImageIcon(new URL("http://www.pd4pic.com/images/blue-background-simple.jpg")));
contentPane.setLayout(new BorderLayout());
frame.add(contentPane, BorderLayout.CENTER);
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.anchor = GridBagConstraints.WEST;
JPanel panel = new JPanel(new GridBagLayout());
panel.setOpaque(false);
JTextField name = new JTextField(20);
JTextField contactNumber = new JTextField(15);
panel.add(getLabel("Name: "), gbc);
gbc.gridwidth = GridBagConstraints.REMAINDER;
panel.add(name, gbc);
gbc.gridwidth = GridBagConstraints.RELATIVE;
panel.add(getLabel("Contact no: "), gbc);
gbc.gridwidth = GridBagConstraints.REMAINDER;
panel.add(contactNumber, gbc);
JLabel topLabel = getLabel("Please enter you details");
topLabel.setHorizontalAlignment(JLabel.CENTER);
contentPane.add(topLabel, BorderLayout.NORTH);
contentPane.add(panel, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
private JLabel getLabel(String text) {
JLabel label = new JLabel(text);
label.setFont(FONT);
label.setForeground(Color.WHITE);
return label;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
new BasicSwingTest2().initUI();
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
});
}
}

Related

How to add JTextField whenever the button is clicked?

I am practising Java Swing and I am trying to create a GPA calculator. I am having a hard time with my code, how can I add text fields whenever the JButton "add" is clicked? I also want the text fields to align vertically when the button is clicked. Should I use a layout or something?
You can check my screenshot as well.
Here is my code:
import java.awt.event.ActionEvent;
import javax.swing.*;
public class gwa implements ActionListener, java.awt.event.ActionListener{
public static void main(String[] args) {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
//button
JButton buttonAdd = new JButton("Add");
buttonAdd.setBounds(30, 30, 80, 34);
buttonAdd.addActionListener(new gwa());
//textfield
JTextField gradeField = new JTextField();
gradeField.setBounds(150, 30, 100, 35);
JTextField unitsField = new JTextField();
unitsField.setBounds(300, 30, 100, 35);
//panel
panel.setLayout(null);
panel.add(buttonAdd);
panel.add(gradeField);
panel.add(unitsField);
//frame
frame.add(panel);
frame.setSize(500,500);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
#Override
public void actionPerformed(ActionEvent e) {
}
One way – but not the only way – is to use GridBagLayout.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
public class GwaAdder {
private static final int COLUMNS = 10;
private GridBagConstraints gbc;
private JPanel textFieldsPanel;
private void addTextField(ActionEvent event) {
JTextField textField = new JTextField(COLUMNS);
gbc.gridy++;
textFieldsPanel.add(textField, gbc);
textFieldsPanel.revalidate();
textFieldsPanel.repaint();
}
private void createAndDisplayGui() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createTextFieldsPanel(), BorderLayout.CENTER);
frame.add(createButtons(), BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createButtons() {
JPanel panel = new JPanel();
JButton button = new JButton("Add");
button.addActionListener(this::addTextField);
panel.add(button);
return panel;
}
private JScrollPane createTextFieldsPanel() {
textFieldsPanel = new JPanel(new GridBagLayout());
gbc = new GridBagConstraints();
gbc.gridy = 0;
JTextField textField = new JTextField(COLUMNS);
textFieldsPanel.add(textField, gbc);
JScrollPane scrollPane = new JScrollPane(textFieldsPanel);
scrollPane.setPreferredSize(new Dimension(140, 200));
return scrollPane;
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new GwaAdder().createAndDisplayGui());
}
}
The ActionListener is implemented using method references. When you change the GUI after it is initially displayed (as the above code does in method addTextField), you usually need to call method revalidate (in class javax.swing.JComponent) followed by method repaint (in class java.awt.Component).
How it looks when I run the above code:
You should first give your button's Action event the panel, and then do the Action
My English is not good, so I use translation software to answer, please forgive me

How do I stop JFrame/JPanel from auto-formatting the distances between my components?

So I'm writing a program which utilizes a GUI. The GUI is built from a JFrame and a JPanel in Java. I have a JTextArea() and a JButton() that appears beside the JTextArea on the left. I also have an image which I imported locally using the method call below ("f" is the variable name of my JFrame):
f.setIconImage(ImageIO.read(new File("image.png")));
I don't mind allowing the users to resize the JFrame but what I dislike is that JFrame automatically reformats the components on my JFrame - specifically the distance between my image and the JTextArea(). I'd like, if possible, to keep the distance between my image and the JTextArea the same regardless of the size the user resizes the JFrame to. Here's the rest of my code if that helps:
public class GUI {
private JFrame f;
private JPanel p;
private JButton b1;
private JLabel lab;
private JTextArea tf;
private static final String FileName = "schedule.txt";
private static final String FileName2 = "schedule2.txt";
public void show()
{
f = new JFrame("Scheduler");
f.setSize(600, 400);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
p = new JPanel();
//p.setPreferredSize(new Dimension(200, 400));
b1 = new JButton("Run");
p.add(b1);
f.add(p);
f.add(p, BorderLayout.SOUTH);
f.add(new JLabel(new ImageIcon("image.png")));
try {
f.setIconImage(ImageIO.read(new File("image.png")));
} catch(Exception z){
System.out.println("Trouble reading file");
}
tf = new JTextArea();
tf.setPreferredSize(new Dimension(300, 200));
p.add(tf);
b1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String text = tf.getText();
try {
FileWriter fw = new FileWriter(FileName);
fw.write(text);
fw.close();
parseInfo();
}
catch(Exception ex)
{
}
}
});
f.setVisible(true);
}
There are any number of ways you "might" achieve this, but the basic answer is, you need to choose one or more layout managers which better meets your needs.
For example, using a GridBagLayout, you can do something like...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.border.LineBorder;
public class JavaApplication1 {
public static void main(String[] args) {
new JavaApplication1();
}
public JavaApplication1() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(8, 8, 8, 8);
JLabel label = new JLabel("Image placeholder") {
// This is done only for demonstration purposes
#Override
public Dimension getPreferredSize() {
return new Dimension(128, 128);
}
};
label.setBorder(new LineBorder(Color.DARK_GRAY));
add(label, gbc);
gbc.gridy++;
gbc.fill = GridBagConstraints.BOTH;
// This will cause the text area to occupy all the avalilable free space
//gbc.weightx = 1;
//gbc.weighty = 1;
JTextArea ta = new JTextArea(10, 20);
add(new JScrollPane(ta), gbc);
JButton btn = new JButton("Run");
gbc.gridy++;
// Reset the constraints
gbc.fill = GridBagConstraints.NONE;
gbc.weightx = 0;
gbc.weighty = 0;
add(btn, gbc);
}
}
}
Take a look at Laying Out Components Within a Container for more details and ideas
Recommendations...
There are a few things in your code that are, "off", but this...
tf = new JTextArea();
tf.setPreferredSize(new Dimension(300, 200));
p.add(tf);
is probably the most striking.
Generally speaking, JTextArea will benefit from been wrapped in a JScrollPane. Also, due to the inconsistencies in how text is rendered across multiple platforms, you should avoid using setPreferredSize (in fact, you should avoid using it in general) and instead rely in the rows, columns constructor, which will make calculations based on the current font and graphics properties.

Automatically Resizing with BorderLayout in Java

This is my jFrame Form with BorderLayout where buttons will be placed in Navigation Bar Panel and jDesktopPane will be placed in Content Panel. The DesktopPane with CardLayout will be displaying different sizes of jPanel Form. I want Content Panel(including whole form) resize based on the different sizes of jPanel Form displayed. Is it possible to do this? If not then I've tried resizing the panel and even the whole form with codes, but it's not working.
I've trying playing with these few codes, but it's not working.
Main_Menu form = new Main_Menu();
form.pack();
form.setSize(900, 548);
form.setPreferredSize(new Dimension(900, 548));
form.validate();
So, based on the limited information available, I wrote a quick test which seems to work just fine
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
CardLayout layout = new CardLayout();
JDesktopPane pane = new JDesktopPane();
Navigator navigator = new Navigator(pane, layout);
pane.setLayout(layout);
pane.setBackground(Color.GREEN);
frame.add(new TopPane(), BorderLayout.NORTH);
frame.add(new NavigationPane(navigator), BorderLayout.WEST);
for (int index = 0; index < 5; index++) {
pane.add(new ContentPane(index), Integer.toString(index));
}
JLabel initial = new JLabel("All your content belong to us");
initial.setBorder(new EmptyBorder(20, 20, 20, 20));
pane.add(initial, "initial");
layout.show(pane, "initial");
frame.add(pane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class Navigator {
private JComponent parent;
private CardLayout layout;
public Navigator(JComponent parent, CardLayout layout) {
this.parent = parent;
this.layout = layout;
}
public void show(String name) {
layout.show(parent, name);
}
}
public class TopPane extends JPanel {
public TopPane() {
setLayout(new GridBagLayout());
setBorder(new EmptyBorder(20, 20, 20, 20));
setBackground(Color.BLUE);
JLabel title = new JLabel("Top Panel");
title.setForeground(Color.WHITE);
add(title);
}
}
public class NavigationPane extends JPanel {
private Navigator navigator;
public NavigationPane(Navigator navigator) {
setLayout(new GridBagLayout());
setBorder(new EmptyBorder(20, 20, 20, 20));
setBackground(Color.ORANGE);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.fill = GridBagConstraints.BOTH;
for (int index = 0; index < 5; index++) {
JButton btn = new JButton("Test " + index);
btn.setActionCommand(Integer.toString(index));
add(btn, gbc);
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String name = e.getActionCommand();
navigator.show(name);
}
});
}
}
}
public class ContentPane extends JPanel {
public ContentPane(int value) {
setLayout(new GridBagLayout());
setBorder(new EmptyBorder(20, 20, 20, 20));
setBackground(Color.MAGENTA);
add(new JLabel("Hello from " + Integer.toString(value)));
}
}
}
Avoid setPreferred/Minimum/MaximumSize, you're overriding the work which the components and the layout managers do in order to provide dynamic sizing hints
If this fails to solve your issue, then consider providing a Minimal, Complete, and Verifiable example
Try to use pack(); not form.pack();. Or setLayout or use CardLayout

Placing the JPanel in JScrollPane [duplicate]

I've got a probelm with my swing ui lately. Everything works fine,untill i trigger a tooltip from a JButton.After that moving the mouse over the rest of the ui is causing weird artifacts and glitching.
Bugged:
I can't show the whole code because its too much but here im initialising the button :
GridBagConstraints bottompane_gbc = new GridBagConstraints();
toggleTorConnectionButton = new JButton();
toggleTorConnectionButton.setToolTipText("Toggles Tor Connection.");
toggleTorConnectionButton.setIcon(new ImageIcon(ResourceHandler.Menueicon3_1));
toggleTorConnectionButton.setMinimumSize(new Dimension(removeFinishedDownloads.getMinimumSize().width, toggleTorConnectionButton.getIcon().getIconHeight()+5));
toggleTorConnectionButton.addActionListener(); // unimportant
bottompane_gbc.gridy = 1;
bottompane_gbc.fill = GridBagConstraints.BOTH;
bottompane_gbc.insets = new Insets(0,15,10,5);
bottompane.add(ToggleTorConnectionButton,bottompane_gbc);
this.add(bottompane,BorderLayout.PAGE_END);
If anybody needs more information to help me pls feel free to ask.Im kind of desperated. XD
EDIT:
After some tinkering im guessing that the problem is related to swing and my use of it.Currently im using alot of Eventlisteners (is this bad?), that might slow down the awt thread ?
Here is a brief extract from HPROF:
http://www.pastebucket.com/96444
EDIT 2:
I was able to recreate the error in a handy and simple example. When you move over the button,wait for the tooltip and then over the ui.You will see ghosting :(.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
public class Main_frame {
public static void main(String[] args) {
new Main_frame();
}
public Main_frame() {
JFrame frame = new JFrame("LOL");
frame.setFocusable(true);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(new Dimension(400, 500));
frame.setLocationRelativeTo(null);
Download_window download_window = new Download_window();
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.addTab("Download", null, download_window, "Main Download Window.");
for (int i = 0; i < 5; i++) {
JPanel pane = new JPanel();
Dimension dim = new Dimension(370, 60);
pane.setPreferredSize(dim);
pane.setMaximumSize(dim);
pane.setBackground(Color.blue);
pane.setMinimumSize(dim);
download_window.jobpanel.add(pane);
}
download_window.jobpanel.repaint();
download_window.jobpanel.revalidate();
frame.add(tabbedPane);
frame.setVisible(true);
}
public class Download_window extends JPanel {
JPanel jobpanel;
public Download_window() {
this.setLayout(new BorderLayout());
jobpanel = new JPanel();
jobpanel.setLayout(new BoxLayout(jobpanel, BoxLayout.Y_AXIS));
JPanel bottompane = new JPanel();
bottompane.setPreferredSize(new Dimension(385, 40));
JButton toggleTorConnectionButton = new JButton();
toggleTorConnectionButton.setPreferredSize(new Dimension(100, 50));
toggleTorConnectionButton.setToolTipText("Toggles Tor Connection.");
bottompane.add(toggleTorConnectionButton);
this.add(bottompane, BorderLayout.PAGE_END);
JScrollPane jobScrollPane = new JScrollPane(jobpanel);
jobScrollPane.getVerticalScrollBar().setUnitIncrement(16);
this.add(jobScrollPane, BorderLayout.CENTER);
}
}
}
Edit 3: Concerning trashgods ideas, I used the EventDispatchThread, I modified the setter to override the getter for size and i crossed out incompatibility by using trashgods code and it was working fine.... So where is the actual difference?
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
public class Main_frame {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Main_frame();
}
});
}
public Main_frame() {
JFrame frame = new JFrame("LOL");
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(new Dimension(400, 500));
Download_window download_window = new Download_window();
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.addTab("Download", null, download_window, "Main Download Window.");
frame.add(tabbedPane);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public class Download_window extends JPanel {
JPanel jobpanel;
public Download_window() {
this.setLayout(new BorderLayout());
jobpanel = new JPanel();
jobpanel.setLayout(new BoxLayout(jobpanel, BoxLayout.Y_AXIS));
for (int i = 0; i < 5; i++) {
JPanel pane = new JPanel(){
#Override
public Dimension getPreferredSize() {
return new Dimension(370, 60);
}
#Override
public Dimension getMaximumSize() {
return new Dimension(370, 60);
}
#Override
public Dimension getMinimumSize() {
return new Dimension(370, 60);
}
};
pane.setBackground(Color.blue);
jobpanel.add(pane);
}
JPanel bottompane = new JPanel(){
#Override
public Dimension getPreferredSize() {
return new Dimension(385, 40);
}
};
JButton toggleTorConnectionButton = new JButton("Button"){
#Override
public Dimension getPreferredSize() {
return new Dimension(100, 30);
}
};
toggleTorConnectionButton.setToolTipText("Toggles Tor Connection.");
bottompane.add(toggleTorConnectionButton);
this.add(bottompane, BorderLayout.PAGE_END);
JScrollPane jobScrollPane = new JScrollPane(jobpanel);
jobScrollPane.getVerticalScrollBar().setUnitIncrement(16);
this.add(jobScrollPane, BorderLayout.CENTER);
}
}
}
Could anyone please verify that strange behavior himself? You just need to copy&paste the code from above in Edit3.
Your code exhibits none of the glitches shown above when run on my platform.
Verify that you have no painting problems e.g. neglecting super.paintComponent() as discussed here.
Verify that you have no driver incompatibilities, as discussed here.
Construct and modify all GUI objects on the event dispatch thread.
Don't use set[Preferred|Maximum|Minimum]Size() when you really mean to override get[Preferred|Maximum|Minimum]Size(), as discussed here. The example below overrides getPreferredSize() on the scroll pane, but you can implement Scrollable, as discussed here.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
/** #see https://stackoverflow.com/a/34319260/230513 */
public class MainFrame {
private static final int H = 64;
public static void main(String[] args) {
EventQueue.invokeLater(() -> new MainFrame());
}
public MainFrame() {
JFrame frame = new JFrame("LOL");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTabbedPane tabbedPane = new JTabbedPane();
JPanel panel = new JPanel(new GridLayout(0, 1, 5, 5));
for (int i = 0; i < 8; i++) {
panel.add(new DownloadPanel());
}
JScrollPane jsp = new JScrollPane(panel) {
#Override
public Dimension getPreferredSize() {
return new Dimension(6 * H, 4 * H);
}
};
tabbedPane.addTab("Download", null, jsp, "Main Download Window.");
tabbedPane.addTab("Options", null, null, "Options");
frame.add(tabbedPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private static class DownloadPanel extends JPanel {
JPanel jobPanel = new JPanel();
public DownloadPanel() {
this.setLayout(new BorderLayout());
this.setBackground(Color.lightGray);
JProgressBar jpb = new JProgressBar();
jpb.setIndeterminate(true);
this.add(jpb);
JPanel buttonPane = new JPanel();
JButton toggleTorConnectionButton = new JButton("Button");
toggleTorConnectionButton.setToolTipText("Toggles Tor Connection.");
buttonPane.add(toggleTorConnectionButton);
this.add(buttonPane, BorderLayout.WEST);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(4 * H, H);
}
}
}

Java GUI layout cannot quite get it right

I tried a bunch of different layouts but none are giving me the desired effect.
I want something like this:
+-----------------------------+
Centered Text
+-------+
|Button |
+-------+
+-----------------------------+
In html it might look like this:
<p align="center">Some text</p>
<input type="button" value="Press"/>
The trouble I am having is with certain layouts (BorderLayout) it likes to resize the button to fit. Other layouts (Boxlayout and GroupLayout) will do something like this:
+-----------------------------+
Centered Text
+-------+
|Button |
+-------+
+-----------------------------+
Even when I have the JLabel aligned to CENTER and the Button aligned to LEFT.
Much appreciation to my helpers.
There are a number layouts that would be able to achieve this, in fact, you might even be able to use BorderLayout and FlowLayout together to do this, but this example simply uses GridBagLayout
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ExampleLayout {
public static void main(String[] args) {
new ExampleLayout();
}
public ExampleLayout() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
JLabel center = new JLabel("Centered Text");
center.setHorizontalAlignment(JLabel.CENTER);
add(center, gbc);
gbc.gridy++;
gbc.fill = GridBagConstraints.NONE;
gbc.gridwidth = 1;
gbc.weightx = 0;
gbc.anchor = GridBagConstraints.WEST;
JButton button = new JButton("Button");
add(button, gbc);
}
}
}
Take a look at Laying Out Components Within a Container for more examples and details
Although MadProgrammer and Costis Aivalis already answered your question, here is also an answer with MigLayout:
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import net.miginfocom.swing.MigLayout;
public class MigLayoutDemo {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
JLabel label = new JLabel("Centered text");
JButton button = new JButton("Button");
public MigLayoutDemo() {
panel.setLayout(new MigLayout());
label.setHorizontalAlignment(JLabel.CENTER);
panel.add(label, "wrap, pushx, growx");
panel.add(button);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(MigLayoutDemo::new);
}
}
Same effect, but this approach is less verbose unlike in case of GridBagLayout and I personally think that MigLayout is easier to use.
FlowLayout(int align) allows you to define justification. The default is CENTER. If you just left justify the FlowLayout of the panel that contains your button it works without having to use GridBagLayout manually. NetBeans provide an excellent GridBagLayout customizer, but you do not want to touch the code it generates automatically.
import javax.swing.*;
import java.awt.*;
public class MyLooks extends JFrame {
public MyLooks() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
p = new JPanel(new GridLayout(2, 1));
p1 = new JPanel();
p2 = new JPanel(new FlowLayout(FlowLayout.LEFT));
myLabel = new JLabel("this is a label");
myButton = new JButton("press");
p1.add(myLabel);
p2.add(myButton);
p.add(p1);
p.add(p2);
setContentPane(p);
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new MyLooks().setVisible(true);
}
});
}
private JLabel myLabel;
private JButton myButton;
private JPanel p, p1, p2;
}

Categories