Reputation: 499
I'm trying to display a string when a button is pressed, but it does not work. I do not know what the problem is. I get no error, but that does not bother me. I'm missing something fundamental, I suppose. Please help!!
//I'm trying to draw a string in the frame when a button is pressed, but it won't work..
//Can't figure out what the problem is.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
class AppletTwo extends JFrame implements ActionListener
{
JFrame frameOne;
JButton btnOne;
AppletTwo()
{
frameOne = new JFrame("frameOne");
frameOne.setSize(320,240);
frameOne.setLayout(new FlowLayout(FlowLayout.LEFT));
frameOne.setVisible(true);
frameOne.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
btnOne = new JButton("Print");
btnOne.addActionListener(this);
frameOne.add(btnOne);
}
public void actionPerformed(ActionEvent ae)
{
if(ae.getSource() == btnOne)
{
repaint();
}
}
public void paint(Graphics g)
{
g.drawString("Never Works",150,150);
}
public static void main(String[] args)
{
AppletTwo frame1 = new AppletTwo();
}
}
Upvotes: 2
Views: 1112
Reputation: 209002
" I'm missing something fundamental, I suppose. "
Yes, you are:
Main problem:
JFrame
which is the component for which you are overriding the paint
method. But you create another instance of a JFrame
, which is the one you setVisible
to. Keep in mind, you haven't drawn anything to this frame. So you are seeing the new instance of frame, not the class frame for which you are painting (and for which you never set visible).Other problems:
You should always call super.paint[Component]
after a paint[Component]
override
@Override
public void paint(Graphics g) {
super.paint(g);
}
Don't paint on top level container like JFrame
. Instead paint on a JPanel
or JComponent
and override is paintComponent
method and call super.paintComponent
, then add that component to the frame. See Performing Custom Painting
Swing apps should be run on the event dispatch thread (EDT). You can do so by wrapping your main
code in a SwingUtilities.invokeLater(...)
. See Initial Threads
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
AppletTwo frame1 = new AppletTwo();
}
});
}
Generally, you always want to set the frame visible after adding your components.
Other notes:
UPDATE
Example with all the above mentioned points.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class SimpleDrawing {
public SimpleDrawing() {
final DrawingPanel panel = new DrawingPanel();
final JTextField field = new JTextField(15);
JButton button = new JButton("Change name");
button.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
String someString = field.getText();
if (!someString.isEmpty()) {
panel.setString(someString);
}
}
});
JPanel bottomPanel = new JPanel();
bottomPanel.add(field);
bottomPanel.add(button);
JFrame frame = new JFrame();
frame.add(panel);
frame.add(bottomPanel, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public class DrawingPanel extends JPanel {
private String someString = "Stackoverflow";
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawString(someString, 75, 75);
}
@Override
public Dimension getPreferredSize() {
return new Dimension (300, 100);
}
public void setString(String someString) {
this.someString = someString;
repaint();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
new SimpleDrawing();
}
});
}
}
Upvotes: 6