I'm also having problem with button.addActionListener(null); inside the () should be "this" but you can't use this in a static context which I don't have an idea of what it means. The core problem of this thread is the JButton and JLabel not showing up when I run the Program. If you have any suggestion where I can read more in depth to have a deeper understanding of JLabels, JFrame, JButton and JPanel please do tell me and I would appreciate that as I am completely new to Programming as a whole. Thank you for any feedbacks. :)
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class GUI implements ActionListener {
private static int count = 0;
private static JLabel label;
public static void gui() {
System.out.println("Hello World!"); // For debugging.
JFrame frame = new JFrame();
JButton button = new JButton("Click");
button.addActionListener(null); // <--- One of my issue!
label = new JLabel("Total Clicks: 0");
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
int x = (int) ((dimension.getWidth() - frame.getWidth()) / 2);
int y = (int) ((dimension.getHeight() - frame.getHeight()) / 2);
int width = x;
int height = y;
int perf_x = (int) x - width/2;
int perf_y = (int) y - height/2;
frame.setLocation(perf_x, perf_y);
ImageIcon icon = new ImageIcon("icon.png");
JPanel panel = new JPanel();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setSize(800,550);
frame.setTitle("Click Counter");
frame.setResizable(true);
frame.setIconImage(icon.getImage());
frame.getContentPane().setBackground(new Color(255, 255, 255));
frame.add(panel, BorderLayout.CENTER );
} // Method
public void actionPerformed(ActionEvent e) {
count++;
label.setText("Total Clicks: " + count);
}
} // Class
I have tried changing the JFrame in a different line to the upper sections of the code if that would make it work but no luck. Instead of a mouse clicker I was met with a blank program.
in this code i changed button.addActionListener(null); to button.addActionListener(new GUI());
new GUI() creates a new instance of the GUI class, which implements the ActionListener interface.
This means that GUI has implemented the required actionPerformed() method that gets called when the button is clicked.
i hope this will help you:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class GUI implements ActionListener {
private static int count = 0;
private static JLabel label;
public static void gui() {
System.out.println("Hello World!"); // For debugging.
JFrame frame = new JFrame();
JButton button = new JButton("Click");
button.addActionListener(new GUI()); // Set the ActionListener to this instance
label = new JLabel("Total Clicks: 0");
ImageIcon icon = new ImageIcon("icon.png");
JPanel panel = new JPanel();
panel.add(button);
panel.add(label);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setSize(800,550);
frame.setTitle("Click Counter");
frame.setResizable(true);
frame.setIconImage(icon.getImage());
frame.getContentPane().setBackground(new Color(255, 255, 255));
frame.add(panel, BorderLayout.CENTER);
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
int x = (int) ((dimension.getWidth() - frame.getWidth()) / 2);
int y = (int) ((dimension.getHeight() - frame.getHeight()) / 2);
int width = x;
int height = y;
int perf_x = (int) x - width/2;
int perf_y = (int) y - height/2;
frame.setLocation(perf_x, perf_y);
} // Method
public static void main(String[] args) {
gui();
}
public void actionPerformed(ActionEvent e) {
count++;
label.setText("Total Clicks: " + count);
}
} // Class
Related
This program just creates a UI1 and a Button. When I click on that button a new UI Appear which I coded so that it doesn't go outside the bounds of UI1. My main problem is that I'm trying to make the width and height of the button smaller so that it looks more like an app icon. But when I set the bounds on the button it doesn't change anything when I run the code.
//Start
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.Objects;
import javax.imageio.ImageIO;
import javax.swing.*;
public class MainUI extends JFrame {//MainUI
private JButton button;
private JPanel panel;
public MainUI() {
//UI1
setSize(1000, 700);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
try {
//Here is the Button--
button = new JButton();
button.setBounds(200,200,70,70);
Image img = ImageIO.read(Objects.requireNonNull(getClass().getResource("icons8-messages-100.png")));
button.setIcon(new ImageIcon(img));
button.setFocusable(false);
panel = new JPanel();
panel.add(button);
add(panel);
button.addActionListener(e -> {
UI2 ui2 = new UI2();
ui2.setLocationRelativeTo(panel);
ui2.setVisible(true);
ui2.addComponentListener(new ComponentAdapter() {
public void componentMoved(ComponentEvent e) {
//This makes the ui2 not go outside the Main UI
int x = ui2.getX();
int y = ui2.getY();
int width1 = getWidth();
int height1 = getHeight();
int width2 = ui2.getWidth();
int height2 = ui2.getHeight();
if (x < getX()) {
ui2.setLocation(getX(), y);
}
if (y < getY()) {
ui2.setLocation(x, getY());
}
if (x + width2 > getX() + width1) {
ui2.setLocation(getX() + width1 - width2, y);
}
if (y + height2 > getY() + height1) {
ui2.setLocation(x, getY() + height1 - height2);
}//end of if statements
}//componentMoved
});//addComponentListener
});//addActionListener
} catch(Exception e) {
System.out.println("Something's Wrong");
}
}//End of MainUI
public static void main(String[] args) {
MainUI mainFrame = new MainUI();
mainFrame.setVisible(true);
}
}//Class MainUI
class UI2 extends JFrame {
public UI2() {
setBounds(getX() + 50, getY() + 50, 200, 200);
setResizable(false);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setLayout(new BorderLayout());
}
}//Class UI2
//End
UI2 should be a dialog and not another JFrame since Swing applications should usually only have a single, top-level container.
You also don't need to do all the hard work yourself of placing GUI components on the screen nor sizing them. You should use layout managers and other, relevant parts of the rich, API – in order to make the JButton look like an app icon.
More notes after the code.
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.Objects;
import javax.imageio.ImageIO;
import javax.swing.*;
public class MainUI {
private JButton button;
private JFrame frame;
private JPanel panel;
private UI2 ui2;
public MainUI() {
frame = new JFrame();
frame.setSize(1000, 700);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try {
button = new JButton();
Image img = ImageIO.read(Objects.requireNonNull(getClass().getResource("icons8-messages-100.png")));
button.setIcon(new ImageIcon(img));
button.setFocusable(false);
button.setContentAreaFilled(false);
button.setBorderPainted(false);
panel = new JPanel();
panel.add(button);
frame.add(panel);
button.addActionListener(e -> {
if (ui2 == null) {
ui2 = new UI2(frame);
}
ui2.setVisible(true);
});// addActionListener
}
catch (Exception e) {
e.printStackTrace();
}
frame.setVisible(true);
}// End of MainUI
public static void main(String[] args) {
EventQueue.invokeLater(() -> new MainUI());
}
}// Class MainUI
#SuppressWarnings("serial")
class UI2 extends JDialog {
public UI2(JFrame owner) {
super(owner);
setSize(200, 200);
setResizable(false);
setLocationRelativeTo(owner);
addComponentListener(new ComponentAdapter() {
public void componentMoved(ComponentEvent e) {
// This makes the ui2 not go outside the Main UI
int x = getX();
int y = getY();
int width1 = owner.getWidth();
int height1 = owner.getHeight();
int width2 = getWidth();
int height2 = getHeight();
if (x < owner.getX()) {
setLocation(owner.getX(), y);
}
if (y < owner.getY()) {
setLocation(x, owner.getY());
}
if (x + width2 > owner.getX() + width1) {
setLocation(owner.getX() + width1 - width2, y);
}
if (y + height2 > owner.getY() + height1) {
setLocation(x, owner.getY() + height1 - height2);
} // end of if statements
}// componentMoved
});// addComponentListener
}
}// Class UI2
(Below notes are in no particular order.)
You don't need to create a new UI2 each time the user clicks the JButton (in UI1). Create it once and then just hide it when you close it and show it when you click the JButton. The default behavior is to hide the JDialog when it is closed.
A Swing application does not need to extend JFrame (or JPanel or any other JComponent). A Swing application can extend JComponent (or subclass thereof) but it does not have to.
The default layout for [the content pane of] JFrame is BorderLayout so no need to explicitly set this.
Printing a message, like Something's Wrong, in a catch block, might be user-friendly but it won't help you find the cause of the exception
. I nearly always print the stack trace in my catch blocks.
Screen capture of running app.
However, since you don't want UI2 to move outside of UI1, an alternative would be to use a JInternalFrame rather than a JDialog. Here is a demonstration.
(Again, there are notes after the code.)
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.util.Objects;
import javax.imageio.ImageIO;
import javax.swing.DefaultDesktopManager;
import javax.swing.DesktopManager;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JPanel;
public class IframTst {
private JDesktopPane desktopPane;
private JInternalFrame iFrame;
public IframTst() throws IOException {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createButton(), BorderLayout.PAGE_START);
frame.add(createDesktopPane(), BorderLayout.CENTER);
frame.setSize(1000, 700);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createButton() throws IOException {
JPanel panel = new JPanel();
JButton button = new JButton();
Image img = ImageIO.read(Objects.requireNonNull(getClass().getResource("icons8-messages-100.png")));
button.setIcon(new ImageIcon(img));
button.setFocusable(false);
button.setContentAreaFilled(false);
button.setBorderPainted(false);
button.addActionListener(this::showIframe);
panel.add(button);
return panel;
}
private JDesktopPane createDesktopPane() {
desktopPane = new JDesktopPane();
DesktopManager manager = new DefaultDesktopManager() {
private static final long serialVersionUID = -4685522430190278205L;
#Override
public void dragFrame(JComponent f, int newX, int newY) {
setBoundsForFrame(f, newX, newY, f.getWidth(), f.getHeight());
}
#Override
public void setBoundsForFrame(JComponent f,
int newX,
int newY,
int newWidth,
int newHeight) {
Rectangle rect = desktopPane.getVisibleRect();
if (newX < 0) {
newX = 0;
}
if (newX + newWidth > rect.width) {
newX = rect.width - newWidth;
}
if (newY < 0) {
newY = 0;
}
if (newY + newHeight > rect.height) {
newY = rect.height - newHeight;
}
super.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
}
};
desktopPane.setDesktopManager(manager);
return desktopPane;
}
private void showIframe(ActionEvent event) {
if (iFrame == null) {
iFrame = new JInternalFrame(null, false, true, false, false);
iFrame.setDefaultCloseOperation(JInternalFrame.HIDE_ON_CLOSE);
iFrame.setSize(200, 200);
desktopPane.add(iFrame);
}
iFrame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
try {
new IframTst();
}
catch (IOException xIo) {
xIo.printStackTrace();
}
});
}
}
The ActionListener is implemented using method references
The inspiration for keeping the JInternalFrame within the bounds of its parent JDesktopPane came from
Preventing JInternalFrame from being moved out of a JDesktopPane
(as well as looking at the source code for class DefaultDesktopManager)
You can also set the initial location of the JInternalFrame within the JDesktopPane. Refer to
How do I open a JInternalFrame centered in a JDesktopPane?
How it looks when I run it.
I'm trying to simulate a drop shadow using non-expensive drawing rectangles, around a JFrame that has a menu bar, but the shadow is showing around the lower part excluding the menu bar.
Any idea how to achieve the effect on the whole window?
package com.dropshadow;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.border.EmptyBorder;
import org.nuiton.jaxx.runtime.swing.ComponentMover;
import org.nuiton.jaxx.runtime.swing.ComponentResizer;
public class DropShadowMenu {
public static void main(String[] args) {
initFrame();
}
private static void initFrame() {
final DropShadowTool shadow = new DropShadowTool();
JFrame frame = new JFrame() {
private static final long serialVersionUID = -512601712971605848L;
#Override
public void paint(Graphics g) {
super.paint(g);
shadow.applyShadow(this, (Graphics2D) g);
}
};
frame.setUndecorated(true);
frame.setBackground(new Color(255, 255, 255, 0));
frame.setPreferredSize(new Dimension(400, 600));
JPanel contentPane = new JPanel() {
private static final long serialVersionUID = -4799881378955761842L;
#Override
public void paint(Graphics g) {
super.paint(g);
shadow.applyShadow(this, (Graphics2D) g);
}
};
contentPane.setBorder(new EmptyBorder(20, 20, 20, 20));
contentPane.setLayout(new BorderLayout());
frame.setContentPane(contentPane);
contentPane.setBackground(new Color(0,0,0,0));
JPanel content = new JPanel();
contentPane.add(content);
JMenuBar menuBar = new JMenuBar();
menuBar.setBorder(new EmptyBorder(0,20,0,20));
menuBar.setBackground(new Color(255, 0, 255, 255));
frame.setJMenuBar(menuBar);
JPanel menuPanel = new JPanel();
menuPanel.setBorder(BorderFactory.createLineBorder(Color.red));
menuPanel.setLayout(new BorderLayout());
JMenu file = new JMenu("File");
file.setMnemonic('f');
JMenuItem exit = new JMenuItem("Exit");
exit.setMnemonic('x');
exit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X,InputEvent.ALT_DOWN_MASK));
menuBar.add(file);
file.add(exit);
exit.addActionListener(e ->
{
System.out.println("Exiting - Bye!");
System.exit(0);
} );
JMenu menu = new JMenu("Menu 1");
menuBar.add(menu);
menu.add(new JMenuItem("Item 1"));
menu.add(new JMenuItem("Item 2"));
JMenu subMenu = new JMenu("SubMenu 1");
subMenu.add(new JMenuItem("Item 3"));
subMenu.add(new JMenuItem("Item 4"));
menuBar.add(Box.createHorizontalGlue());
JButton x = new JButton("X");
x.setBorder(null);
x.setBackground(new Color(0,0,0,0));
menuBar.add(x);
x.addActionListener(e -> System.exit(0));
menu.add(subMenu);
content.setLayout(new BorderLayout());
JButton button = new JButton("bla blah");
button.addActionListener(e->System.out.println("bla bla button"));
content.add(button, BorderLayout.SOUTH);
content.setBackground(new Color(255,255,255));
JButton jx = new JButton(". X .");
jx.setBackground(new Color(255,255,255));
menuPanel.add(jx, BorderLayout.EAST);
jx.addActionListener(e -> System.exit(0));
ComponentMover cm = new ComponentMover();
cm.registerComponent(frame);
ComponentResizer cr = new ComponentResizer();
cr.registerComponent(frame);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
private static List<Color> colors = new ArrayList<Color>();
static {
for (int i=0;i<20;i++) {
colors.add(new Color(0, 0, 0, 5*i));
}
}
private static class DropShadowTool {
private void applyShadow(Container c, Graphics2D g) {
if(c.getName().equals("Charbel"))
System.out.println(c);
Insets insets = c.getInsets();
System.out.println(insets);
Dimension size = c.getSize();
int x0 = 0;
int xi = insets.left;
int y0 = 0;
int yi = insets.top;
int width0 = size.width;
int widthi = size.width - xi - insets.right;
int height0 = size.height;
int heighti = size.height - yi - insets.bottom;
int last = 0;
for (int i = 0; i < insets.left; i++) {
last = i;
drawLines(g, x0, y0, width0, height0, i);
}
drawLines(g, x0, y0, width0, height0, last);
}
private void drawLines(Graphics2D g, int x0, int y0, int width0, int height0, int i) {
int x = x0 + i;
int y = y0 + i;
int width = width0 - i - i;
int height = height0 - i - i;
g.setColor(colors.get(i % colors.size()));
g.drawRect(x, y, width, height);
}
}
}
I would suggest that your drop shadow is just is just a custom Border and should be implemented as such.
Then you should be able to add the DropShadowBorder to any Swing component without doing any custom painting on the component.
Then I would suggest you can set the Border of the JRootPane. The root pane manages both the menu bar and the content pane at a higher level so the border should be around both components.
Read the section from the Swing tutorial on The Root Pane.
I have this code that creates a Jframe where I add a JLabel with a picture and a JpasswordField. I want the JpasswordField to be on top of the image but only depending on where I do the f.add I get one of them showed or not... I want the JpasswordField to be on top of the picture to allow the user to introduce a password but with the picture as background.
Here is the code:
package java;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPasswordField;
public class Java implements Runnable {
public static void main(String[] args) {
EventQueue.invokeLater(new Java());
}
#Override
public void run() {
JFrame f = new JFrame();
/*Keep on front*/
f.toFront();
f.repaint();
f.setAlwaysOnTop(true);
f.setExtendedState( f.getExtendedState()|JFrame.MAXIMIZED_BOTH );
f.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
f.setUndecorated(true);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
f.setBounds(0,0,screenSize.width-5, screenSize.height-100);
double width = screenSize.getWidth();
double height = screenSize.getHeight();
System.out.println(width+" "+height);
BufferedImage myPicture = null;
try {
myPicture = ImageIO.read(new File("C:\\image.jpg"));
} catch (IOException e1) {
e1.printStackTrace();
}
Image dimg = myPicture.getScaledInstance((int)width, (int)height,Image.SCALE_SMOOTH);
JLabel picLabel = new JLabel(new ImageIcon(dimg));
JPasswordField myTextfield = new JPasswordField("Password");
myTextfield.setEchoChar('*'); // U+26AB
picLabel.setPreferredSize(screenSize);
picLabel.setVerticalAlignment(JLabel.BOTTOM);
/*Depending of who I add first the image or the JPasswordField is showed*/
f.add(myTextfield);
f.add(picLabel);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
First off, your code should be geared towards creating JPanels, and you should control the layout manager of this JPanel directly. Then you can place and display your JPanel in a JDialog not a JFrame, since much of your code appears to be trying to emulate a dialog's actions (such as keeping it on top and such).
That being sad, one of your big problems is that you're ignoring the layout manager that the JFrame's contentPane is using, the BorderLayout. By adding components to it in a default fashion, you will cover up anything that was added to the same position previously. Instead I suggest:
Create a JPanel
Draw your image as a background image in the JPanel's paintComponent methd.
Add your JLabel to your JPanel.
Display the JPanel in a JDialog not a JFrame.
For example:
import java.awt.Color;
import java.awt.Component;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class DialogExample extends JPanel {
private static final int COLUMN_COUNT = 10;
private static final int I_GAP = 3;
public static final String BKG_IMG_PATH = "http://upload.wikimedia.org/wikipedia/commons/"
+ "thumb/9/92/Camels_in_Jordan_valley_%284568207363%29.jpg/800px-Camels_in_Jordan_valley_"
+ "%284568207363%29.jpg";
private BufferedImage backgrndImage;
private JTextField userNameField = new JTextField();
private JPasswordField passwordField = new JPasswordField();
private JPanel mainPanel = new JPanel(new GridBagLayout());
private JButton okButton = new JButton("OK");
private JButton cancelButton = new JButton("Cancel");
public DialogExample(BufferedImage backgrndImage) {
this.backgrndImage = backgrndImage;
userNameField.setColumns(COLUMN_COUNT);
passwordField.setColumns(COLUMN_COUNT);
JPanel btnPanel = new JPanel(new GridLayout(1, 0, 5, 5));
btnPanel.setOpaque(false);
btnPanel.add(okButton);
btnPanel.add(cancelButton);
GridBagConstraints gbc = getGbc(0, 0, GridBagConstraints.BOTH);
mainPanel.add(createLabel("User Name", Color.white), gbc);
gbc = getGbc(1, 0, GridBagConstraints.HORIZONTAL);
mainPanel.add(userNameField, gbc);
gbc = getGbc(0, 1, GridBagConstraints.BOTH);
mainPanel.add(createLabel("Password:", Color.white), gbc);
gbc = getGbc(1, 1, GridBagConstraints.HORIZONTAL);
mainPanel.add(passwordField, gbc);
gbc = getGbc(0, 2, GridBagConstraints.BOTH, 2, 1);
mainPanel.add(btnPanel, gbc);
mainPanel.setOpaque(false);
add(mainPanel);
}
private JLabel createLabel(String text, Color color) {
JLabel label = new JLabel(text);
label.setForeground(color);
return label;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (backgrndImage != null) {
g.drawImage(backgrndImage, 0, 0, this);
}
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet() || backgrndImage == null) {
return super.getPreferredSize();
}
int imgW = backgrndImage.getWidth();
int imgH = backgrndImage.getHeight();
return new Dimension(imgW, imgH);
}
public static GridBagConstraints getGbc(int x, int y, int fill) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbc.insets = new Insets(I_GAP, I_GAP, I_GAP, I_GAP);
gbc.fill = fill;
return gbc;
}
public static GridBagConstraints getGbc(int x, int y, int fill, int width,
int height) {
GridBagConstraints gbc = getGbc(x, y, fill);
gbc.gridwidth = width;
gbc.gridheight = height;
return gbc;
}
private static void createAndShowGui() throws IOException {
final JFrame frame = new JFrame("Frame");
final JDialog dialog = new JDialog(frame, "User Sign-In", ModalityType.APPLICATION_MODAL);
URL imgUrl = new URL(BKG_IMG_PATH);
BufferedImage img = ImageIO.read(imgUrl);
final DialogExample dlgExample = new DialogExample(img);
dialog.add(dlgExample);
dialog.pack();
JPanel mainPanel = new JPanel();
mainPanel.add(new JButton(new AbstractAction("Please Press Me!") {
#Override
public void actionPerformed(ActionEvent e) {
dialog.setVisible(true);
}
}));
mainPanel.setPreferredSize(new Dimension(800, 650));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
createAndShowGui();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
Just to give one example (amongst many other possibilities), here is a small snippet that shows how to handle this.
Btw, when you call f.pack(); f.setLocationRelativeTo(null);, then this call is useless: f.setBounds(0,0,screenSize.width-5, screenSize.height-100);
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPasswordField;
import javax.swing.SwingUtilities;
public class BasicSwingTest2 {
private JFrame frame;
protected void initUI() throws MalformedURLException {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
askForPassword();
}
private void askForPassword() {
final JDialog dialog = new JDialog(frame);
dialog.setResizable(false);
BufferedImage myPicture = null;
try {
myPicture = ImageIO
.read(new URL("http://images.all-free-download.com/images/graphiclarge/blue_abstract_background_310971.jpg"));
} catch (IOException e1) {
e1.printStackTrace();
}
Image dimg = myPicture.getScaledInstance(Toolkit.getDefaultToolkit().getScreenSize().width * 2 / 3, Toolkit.getDefaultToolkit()
.getScreenSize().height * 2 / 3, Image.SCALE_SMOOTH);
JLabel picLabel = new JLabel(new ImageIcon(dimg));
picLabel.setLayout(new GridBagLayout());
final JPasswordField password = new JPasswordField(25);
password.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Password is " + new String(password.getPassword()));
dialog.setVisible(false);
}
});
picLabel.add(password);
dialog.add(picLabel);
dialog.setTitle("Enter your password");
dialog.pack();
dialog.setLocationRelativeTo(frame);
dialog.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
new BasicSwingTest2().initUI();
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
});
}
}
I am trying to create a GUI that will take in the number of circles to draw, and draw them in drawPanel with random locations/sizes. On my actionListener, when I try to draw the circle, it gives me red lines on my drawOval
1st class:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextArea;
/**
*
* #author Chris
*
*/
public class CirclesPanel extends JPanel{
private JButton draw, clear;
private JTextArea textArea;
private JPanel panel, drawPanel, buttonPanel;
private int count;
/**constructor
* builds the frame
*/
public CirclesPanel(){
//creates buttons and textArea
draw = new JButton("Draw");
clear = new JButton("Clear");
textArea = new JTextArea(1,10);
textArea.setBorder(BorderFactory.createTitledBorder("Circles"));
//creats panel
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
setPreferredSize(new Dimension(620, 425));
//creates subpanel drawPanel
JPanel drawPanel = new JPanel();
drawPanel.setPreferredSize(new Dimension(450,400));
drawPanel.setBackground(Color.BLACK);
//creates subpanel buttonPanel
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(3,1));
//adds all the content to the frame
add(panel);
add(buttonPanel, BorderLayout.WEST);
add(drawPanel, BorderLayout.EAST);
buttonPanel.add(textArea);
buttonPanel.add(draw);
buttonPanel.add(clear);
//reads if the draw button is clicked
draw.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
count =Integer.parseInt(textArea.getText());//takes the count in
repaint();//repaints the picture to add the circles
}
});
//reads if the clear button is clicked
clear.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
count=0;//sets the count to 0 so nothing is painted
repaint();//repaints the window
}
});
}
/**Paint component
* draws the random circles
*/
public void paintComponent(Graphics g) {
Random generator = new Random();
int x, y, diameter;
for(int i = 0; i < count; i++){ //loop that takes the count and does this "x" times
g.setColor(Color.BLUE);//sets color to blue
x = generator.nextInt(90);//random location for x
y = generator.nextInt(90);//random location for y
diameter = generator.nextInt(30);//random size
g.fillOval(x, y, diameter, diameter);//draws the circle
}
}
}
2nd class
import javax.swing.JFrame;
public class Circles {
public static void main(String[]args){
JFrame frame = new JFrame("Cicles HW9");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new CirclesPanel());
frame.pack();
frame.setVisible(true);
}
}
So in your, I did little addition, first of all, I made the whole program in one class(CIRLCES PANEL), IF You want to use the second class, you can use it....
Problem is coming, your program is not the reading the ActionPerformed method for the drawing, means it is not located with the button, now I directly added it with your button(DRAW), now whenever you click on the button, it automatically reads the your textArea value, and draw your circles. I made your text area FINAL, So you can use it anywhere......
Now things that you need to do----
- this program is drawing circle on the whole frame, means not on your drawing Panel, you need to set the values, so it will draw on your draw panel area
- Also you need to add color for your oval, because it will either draw black color circle, which you will not able to see.....
and also one thing I forget to mentioned you, is that your, you also need to add code for your clear method...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextArea;
public class CirclesPanel extends JPanel{
private JButton draw, clear;
private JTextArea textArea;
private JPanel panel, drawPanel, buttonPanel;
private int count;
public CirclesPanel(){
JButton draw = new JButton("Draw");
JButton clear = new JButton("Clear");
final JTextArea textArea = new JTextArea(1,10);
textArea.setBorder(BorderFactory.createTitledBorder("Circles"));
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
setPreferredSize(new Dimension(620, 425));
JPanel drawPanel = new JPanel();
drawPanel.setPreferredSize(new Dimension(450,400));
drawPanel.setBackground(Color.BLACK);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(3,1));
add(panel);
add(buttonPanel, BorderLayout.WEST);
add(drawPanel, BorderLayout.EAST);
buttonPanel.add(textArea);
buttonPanel.add(draw);
buttonPanel.add(clear);
draw.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
count =Integer.parseInt(textArea.getText());
repaint();
}
});
}
public void paintComponent(Graphics g) {
Random generator = new Random();
int x, y, diameter;
for(int i = 0; i < count; i++){
x = generator.nextInt(90);
y = generator.nextInt(90);
diameter = generator.nextInt(30);
g.drawOval(x, y, diameter, diameter);
}
}
}
What you want to do is drawing some random circles on the drawPanel when button clicked. I write you a simplified version to show how things work.
I only keep the drawButton and paintPanel to keep things simple.
public class PaintFrame extends JFrame {
private JPanel content = new JPanel();
private JButton drawButton = new JButton("Draw");
private PaintPanel paintPanel = new PaintPanel();
public PaintFrame() {
getContentPane().add(content);
content.setLayout(new BorderLayout());
drawButton.setSize(100, 500);
drawButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// drawButton is fired, repaint the paintPanel
paintPanel.repaint();
}
});
content.add(drawButton, BorderLayout.WEST);
content.add(paintPanel, BorderLayout.CENTER);
}
}
You need a new class extending the JPanel and override the paintComponent method to do the paint job for you. This makes sure you are drawing on the panel.
class PaintPanel extends JPanel {
public PaintPanel() {
setSize(500, 500);
setBackground(Color.BLACK);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Random random = new Random();
g.setColor(Color.WHITE);
// draw 5 random circles
int count = 5;
for (int i = 0; i < count; i++) {
g.drawOval(random.nextInt(250), random.nextInt(250),
random.nextInt(250), random.nextInt(250));
}
}
}
Main class
public class DrawMain {
public static void main(String[] args) {
JFrame frame = new PaintFrame();
frame.setDefaultCloseOperation(PaintFrame.EXIT_ON_CLOSE);
frame.setSize(600, 500);
frame.setVisible(true);
}
}
I need to resize the font of multiple JLabel based on the scaling factor used to resize the container. To do this, I am setting the font of each JLabel to null so that they take the font of the container. It works, but it also produces strange results.
To be specific, the text seems to "lag" behind the container and sometimes it gets even truncated. I would like to avoid this behavior. Any idea how?
Example code simulating the behavior:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.geom.AffineTransform;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class TextResize implements Runnable {
public static void main(String[] args) {
TextResize example = new TextResize();
SwingUtilities.invokeLater(example);
}
public void run() {
JFrame frame = new JFrame("JLabel Text Resize");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(800, 400));
Container container = frame.getContentPane();
container.setLayout(new BorderLayout());
final JPanel labelContainer = new JPanel(new GridBagLayout());
labelContainer.setBorder(BorderFactory.createLineBorder(Color.black));
//initial font
final Font textFont = new Font("Lucida Console", Font.PLAIN, 10).deriveFont(AffineTransform.getScaleInstance(1, 1));
labelContainer.setFont(textFont);
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.BOTH;
c.insets = new Insets(0, 10, 0, 10);
c.weightx = 1;
for (int i = 0; i < 5; i++) {
JLabel f = new JLabel("Text here with possibly looooooooong words");
f.setBorder(BorderFactory.createLineBorder(Color.green));
f.setFont(null);//take the font from parent
c.gridy = i;
labelContainer.add(f, c);
}
JSlider slider = new JSlider(0,50000,10000);
slider.addChangeListener(new ChangeListener() {
double containerWidth = labelContainer.getPreferredSize().getWidth();
double containerHeight = labelContainer.getPreferredSize().getHeight();
#Override
public void stateChanged(ChangeEvent ev) {
JSlider source = (JSlider) ev.getSource();
double scale = (double) (source.getValue() / 10000d);
//scaling the container
labelContainer.setSize((int) (containerWidth * scale), (int) (containerHeight * scale));
//adjusting the font: why does it 'lag' ? why the truncation at times?
Font newFont = textFont.deriveFont(AffineTransform.getScaleInstance(scale, scale));
labelContainer.setFont(newFont);
//print (font.getSize() does not change?)
System.out.println(scale + " " + newFont.getTransform() + newFont.getSize2D());
}
});
container.add(slider, BorderLayout.NORTH);
JPanel test = new JPanel();
test.setLayout(null);
labelContainer.setBounds(5, 5, labelContainer.getPreferredSize().width, labelContainer.getPreferredSize().height);
test.add(labelContainer);
container.add(test, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
}
Picture:
http://i.stack.imgur.com/tZLOO.png
Thanks,
-s
You can use any of the following methods:
by #trashgod
by #StanislavL
by #coobird
I sort of solved the problem adding:
#Override
protected void paintComponent(Graphics g) {
final Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(java.awt.RenderingHints.KEY_TEXT_ANTIALIASING, java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
super.paintComponent(g2d);
}
Thanks anyway.
If performance speed is an issue, then you might find the following information about the 3 methods pointed to by MKorbel above useful.
Coobird's code has some limitations if used on a multi-call basis (eg in a sizeChanged Listener or a LayoutManager)
Trashgod's method is between 2 and 4 times slower than Stanislav's (but it also is designed to fill the area BOTH directions as the OP asked in that question, so not unexpected.)
The code below improves on Stanislav's rectangle method (by starting from the current font size each time rather than reverting back to MIN_FONT_SIZE each time) and thus runs between 20 and 50 times faster than that code, especially when the window/font is large.
It also addresses a limitation in that code which only effectively works for labels located at 0,0 (as in the sample given there). The code below works for multiple labels on a panel and at any location.
import javax.swing.*;
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
// Improved version of http://java-sl.com/tip_adapt_label_font_size.html
public class FontResizingLabel extends JLabel {
public static final int MIN_FONT_SIZE=3;
public static final int MAX_FONT_SIZE=240;
Graphics g;
int currFontSize = 0;
public FontResizingLabel(String text) {
super(text);
currFontSize = this.getFont().getSize();
init();
}
protected void init() {
addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
adaptLabelFont(FontResizingLabel.this);
}
});
}
protected void adaptLabelFont(JLabel l) {
if (g==null) {
return;
}
currFontSize = this.getFont().getSize();
Rectangle r = l.getBounds();
r.x = 0;
r.y = 0;
int fontSize = Math.max(MIN_FONT_SIZE, currFontSize);
Font f = l.getFont();
Rectangle r1 = new Rectangle(getTextSize(l, l.getFont()));
while (!r.contains(r1)) {
fontSize --;
if (fontSize <= MIN_FONT_SIZE)
break;
r1 = new Rectangle(getTextSize(l, f.deriveFont(f.getStyle(), fontSize)));
}
Rectangle r2 = new Rectangle();
while (fontSize < MAX_FONT_SIZE) {
r2.setSize(getTextSize(l, f.deriveFont(f.getStyle(),fontSize+1)));
if (!r.contains(r2)) {
break;
}
fontSize++;
}
setFont(f.deriveFont(f.getStyle(),fontSize));
repaint();
}
private Dimension getTextSize(JLabel l, Font f) {
Dimension size = new Dimension();
//g.setFont(f); // superfluous.
FontMetrics fm = g.getFontMetrics(f);
size.width = fm.stringWidth(l.getText());
size.height = fm.getHeight();
return size;
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
this.g=g;
}
public static void main(String[] args) throws Exception {
FontResizingLabel label=new FontResizingLabel("Some text");
JFrame frame=new JFrame("Resize label font");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(label);
frame.setSize(300,300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}