I wrote the self contained example below and I have it working pretty much the way I want except for one thing. Currently, if the user clicks an Ellipse2D it will highlight a cell in the JTable and allow them to input strings. The problem is that when you close the program it doesn't save the values to Object[][] data.
How do I save the input to Object[][] data so that the next time I run the application it is present?
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.*;
import java.util.*;
import javax.swing.*;
public class SelfContainedExample extends JPanel implements MouseListener {
private Map<Ellipse2D.Double, Point> shapesMap = new HashMap<>();
private Ellipse2D.Double[] ellipses = new Ellipse2D.Double[] {
new Ellipse2D.Double(50, 100, 30, 30),
new Ellipse2D.Double(175, 100, 30, 30),
new Ellipse2D.Double(300, 100, 30, 30),
new Ellipse2D.Double(50, 160, 30, 30),
new Ellipse2D.Double(175, 160, 30, 30),
new Ellipse2D.Double(300, 160, 30, 30)};
static Object[][] data = {{"1_1", "1_2", "1_3"},
{"2_1", "2_2", "2_3"},
{"3_1", "2_2", "2_3"},
{"4_1", "2_2", "2_3"},
{"5_1", "2_2", "2_3"},
{"6_1", "2_2", "2_3"}};
static Object[] columnNames = {"1", "2", "3"};
static JTable jtable = new JTable(data, columnNames);
public static void main(String[] args)
{
EventQueue.invokeLater(() -> createAndShowGUI());
}
public SelfContainedExample() {
int row = 0;
int column = 0;
for (Ellipse2D.Double ellipse : ellipses) {
shapesMap.put(ellipse, new Point(row, column));
row++;
}
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g.create();
g2d.setColor(Color.BLACK);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
for (Ellipse2D ellipse : ellipses) {
g2d.fill(ellipse);
}
g2d.setStroke(new BasicStroke(3));
g2d.setColor(Color.GRAY);
for (Ellipse2D ellipse : ellipses) {
g2d.draw(ellipse);
}
addMouseListener(this);
g2d.dispose();
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("Example");
JPanel panel = new JPanel();
JPanel tablePanel = new JPanel();
JScrollPane jScrollPane = new JScrollPane(jtable);
jScrollPane.setPreferredSize(new Dimension(385, 119));
tablePanel.add(jScrollPane);
tablePanel.setSize(200, 200);
panel.setLayout(new BorderLayout());
panel.add(new SelfContainedExample(), BorderLayout.CENTER);
panel.add(tablePanel, BorderLayout.SOUTH);
panel.setOpaque(true);
panel.setVisible(true);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setLocationByPlatform(false);
frame.setLocationRelativeTo(null);
frame.setContentPane(panel);
frame.setVisible(true);
}
#Override
public void mouseClicked(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
for (Ellipse2D.Double ellipse : ellipses) {
if (ellipse.contains(e.getPoint())) {
jtable.requestFocusInWindow();
Point p = shapesMap.get(ellipse);
jtable.editCellAt(p.x, p.y);
break;
}
}
}
#Override
public void mouseReleased(MouseEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseExited(MouseEvent e) {}
}
Related
Why does my JPanel not show in JFrame after button is clicked.
There's my code:
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.DefaultListModel;
import javax.swing.AbstractListModel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.JButton;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JPanel;
public class Main {
private JFrame frame;
private JTable table;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Main window = new Main();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Main() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setResizable(false);
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
table = new JTable();
table.setModel(new DefaultTableModel(
new Object[][] {
{"1", "Marcin Zelek", "537573656"},
{"2", "Krzysztof Tomala", "324159103"},
{"3", "Zbigniew S", "324159104"},
},
new String[] {
"#", "Name", "Phone number"
}
));
table.getColumnModel().getColumn(1).setPreferredWidth(214);
table.getColumnModel().getColumn(2).setPreferredWidth(246);
table.setBounds(12, 103, 426, 185);
frame.getContentPane().add(table);
JButton btnDodajNowy = new JButton("Dodaj nowy");
btnDodajNowy.addMouseListener(new MouseAdapter() {
#Override
public void mouseReleased(MouseEvent arg0) {
JPanel panel = new JPanel(null);// Creating the JPanel
panel.setBounds(0, 243, 286, 150);
panel.setVisible(true);
JButton button = new JButton("New button");
button.setBounds(12, 12, 117, 25);
panel.add(button);
frame.getContentPane().add(panel);
}
});
btnDodajNowy.setBounds(12, 30, 117, 25);
frame.getContentPane().add(btnDodajNowy);
JButton btnUsuZaznaczone = new JButton("Usuń zaznaczone");
btnUsuZaznaczone.addMouseListener(new MouseAdapter() {
#Override
public void mouseReleased(MouseEvent arg0) {
DefaultTableModel model = (DefaultTableModel) table.getModel();
int[] selection = table.getSelectedRows();
for (int i = 0; i < selection.length; i++)
{
model.removeRow(selection[i]-i);
}
}
});
btnUsuZaznaczone.setBounds(141, 30, 204, 25);
frame.getContentPane().add(btnUsuZaznaczone);
}
}
Thanks.
You should use actionListener instead:
btnDodajNowy.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JPanel panel = new JPanel();// Creating the JPanel
panel.setBounds(0, 243, 286, 150);
JButton button = new JButton("New button");
button.setBounds(12, 12, 117, 25);
panel.add(button);
frame.getContentPane().add(panel);
frame.repaint();
}
});
and also:
You don't need to pass null as a parameter to the JPanel constructor
You might want to add a frame.repaint()
You don't need to set the JPanel to visible via setVisible().
If you looking to present the panel in same jframe where you added the button you probably should use CardLayout here is the link http://docs.oracle.com/javase/tutorial/uiswing/layout/card.html
It is being added, however, it is hiding below the JTable. The quickest fix is this:
public void mouseReleased(MouseEvent arg0) {
//...
panel.setBounds(0, 300, 286, 150); // 300 is on the y axis
//...
// then render the frame again:
frame.revalidate();
frame.repaint();
}
However, I suggest to rewrite it a little:
this.generalPanel = new JPanel();
frame.getContentPane().add(generalPanel);
...
generalPanel.add(table);
This way you'll get a good Layout for the topmost container.
I have a JPanel with a JLabel which owns an Icon picture.
how do I set a transparent red color at the top of the whole JPanel (including JLabel Icon)?
I have the transparent backgriound color on for the panel but I want the whole panel including the picture and everything get this transparent color. something like a transparent colorful glass at the top of the JPanel
import java.awt.Color;
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.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class TransparentJLabel {
private static final String IMAGE_PATH = "http://duke.kenai.com/Oracle/OracleStratSmall.png";
private static void createAndShowUI() {
JPanel panel = new JPanel();
panel.setBackground(Color.pink);
URL imageUrl;
try {
imageUrl = new URL(IMAGE_PATH);
BufferedImage image = ImageIO.read(imageUrl);
ImageIcon icon = new ImageIcon(image);
JLabel label = new JLabel(icon);
panel.add(label);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
JFrame frame = new JFrame("TransparentJLabel");
frame.getContentPane().add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
If you just need a layered panel over the whole contentPane, a simple glassPane will do fine (override it's paintComponent(...) method). For example:
JPanel glassPane = new JPanel() {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
g2.setColor(new Color(0, 100, 0, 100));
g2.fillRect(0, 0, getWidth(), getHeight());
g2.dispose();
}
};
glassPane.setOpaque(false);
frame.setGlassPane(glassPane);
frame.getGlassPane().setVisible(true);
However, if you want a layered panel over only one JPanel, I would use JLayer combined with LayerUI, as MadProgrammer already mentioned. You will need a custom LayerUI in which you override the paint(Graphics g, JComponent c) method. I know that sounds dangerous, but I honestly don't know of another way of doing it...
I've provided an example below, this is the output:
As you can see, panel1 (or more accurately, the JLayer) is slighty transparent (RGBA = "0, 100, 0, 100") and panel2 is normal.
Code:
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
import javax.swing.plaf.LayerUI;
public class Example {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Example();
}
});
}
public Example() {
JFrame frame = new JFrame("Example");
JPanel panel1 = new JPanel();
panel1.add(new JButton("Panel 1"));
MyLayerUI layerUI = new MyLayerUI();
JLayer<JPanel> panel1Layer = new JLayer<JPanel>(panel1, layerUI);
panel1.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
if (layerUI.hasOverlay()) {
layerUI.setOverlay(false);
} else {
layerUI.setOverlay(true);
}
panel1Layer.repaint();
}
});
JPanel panel2 = new JPanel();
panel2.add(new JButton("Panel 2"));
JPanel contentPane = new JPanel(new GridLayout(2, 1));
contentPane.add(panel1Layer);
contentPane.add(panel2);
frame.setContentPane(contentPane);
frame.setSize(300, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
class MyLayerUI extends LayerUI<JPanel> {
private boolean overlay = true;
#Override
public void paint(Graphics g, JComponent c) {
super.paint(g, c);
if (hasOverlay()) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setColor(new Color(0, 100, 0, 100));
g2.fillRect(0, 0, c.getWidth(), c.getHeight());
g2.dispose();
}
}
public boolean hasOverlay() {
return overlay;
}
public void setOverlay(boolean overlay) {
this.overlay = overlay;
}
}
Like the one we add into the corner of presentation slides.
I already have SwingX library added and working, in case that could help with something.
Basically, you want to use a JLabel for displaying the date/time, a javax.swing.Timer set to a regular interval to update the label and a DateFormat instance to format the date value...
public class PlaySchoolClock {
public static void main(String[] args) {
new PlaySchoolClock();
}
public PlaySchoolClock() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new ClockPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ClockPane extends JPanel {
private JLabel clock;
public ClockPane() {
setLayout(new BorderLayout());
clock = new JLabel();
clock.setHorizontalAlignment(JLabel.CENTER);
clock.setFont(UIManager.getFont("Label.font").deriveFont(Font.BOLD, 48f));
tickTock();
add(clock);
Timer timer = new Timer(500, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
tickTock();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.setInitialDelay(0);
timer.start();
}
public void tickTock() {
clock.setText(DateFormat.getDateTimeInstance().format(new Date()));
}
}
}
This example uses a time interval of half a second. The main reason for this is I don't go to the trouble of trying to calculate how far we are away from the next second when we set up the initial delay. This ensures that we are always up-to-date
The next question is to ask "why?" This kind of setup is relatively expensive, with the timer firing every half second (to catch any edge cases) and updating the screen, when most OS's actually have a date/time already on the screen...IMHO
I created a JStatusBar from many nested JPanels. I was surprised at how many JPanels it took to create a status bar.
JPanels. JPanels everywhere.
Here's the test GUI.
And here's the JStatusBar class. The status bar has a leftmost status update area. On the right, you can add as many status areas as you want, with a separator bar. The only limit is the width of the status bar.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.JPanel;
public class JStatusBar extends JPanel {
private static final long serialVersionUID = 1L;
protected JPanel leftPanel;
protected JPanel rightPanel;
public JStatusBar() {
createPartControl();
}
protected void createPartControl() {
setLayout(new BorderLayout());
setPreferredSize(new Dimension(getWidth(), 23));
leftPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 5, 3));
leftPanel.setOpaque(false);
add(leftPanel, BorderLayout.WEST);
rightPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING, 5, 3));
rightPanel.setOpaque(false);
add(rightPanel, BorderLayout.EAST);
}
public void setLeftComponent(JComponent component) {
leftPanel.add(component);
}
public void addRightComponent(JComponent component) {
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEADING, 5, 0));
panel.add(new SeparatorPanel(Color.GRAY, Color.WHITE));
panel.add(component);
rightPanel.add(panel);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int y = 0;
g.setColor(new Color(156, 154, 140));
g.drawLine(0, y, getWidth(), y);
y++;
g.setColor(new Color(196, 194, 183));
g.drawLine(0, y, getWidth(), y);
y++;
g.setColor(new Color(218, 215, 201));
g.drawLine(0, y, getWidth(), y);
y++;
g.setColor(new Color(233, 231, 217));
g.drawLine(0, y, getWidth(), y);
y = getHeight() - 3;
g.setColor(new Color(233, 232, 218));
g.drawLine(0, y, getWidth(), y);
y++;
g.setColor(new Color(233, 231, 216));
g.drawLine(0, y, getWidth(), y);
y++;
g.setColor(new Color(221, 221, 220));
g.drawLine(0, y, getWidth(), y);
}
}
The separator bar is yet another JPanel.
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class SeparatorPanel extends JPanel {
private static final long serialVersionUID = 1L;
protected Color leftColor;
protected Color rightColor;
public SeparatorPanel(Color leftColor, Color rightColor) {
this.leftColor = leftColor;
this.rightColor = rightColor;
setOpaque(false);
}
#Override
protected void paintComponent(Graphics g) {
g.setColor(leftColor);
g.drawLine(0, 0, 0, getHeight());
g.setColor(rightColor);
g.drawLine(1, 0, 1, getHeight());
}
}
And finally, the simulator class that shows you how to use the JStatusBar.
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class StatusBarSimulator implements Runnable {
protected TimerThread timerThread;
#Override
public void run() {
JFrame frame = new JFrame();
frame.setBounds(100, 200, 400, 200);
frame.setTitle("Status Bar Simulator");
Container contentPane = frame.getContentPane();
contentPane.setLayout(new BorderLayout());
JStatusBar statusBar = new JStatusBar();
JLabel leftLabel = new JLabel("Your application is running.");
statusBar.setLeftComponent(leftLabel);
final JLabel dateLabel = new JLabel();
dateLabel.setHorizontalAlignment(JLabel.CENTER);
statusBar.addRightComponent(dateLabel);
final JLabel timeLabel = new JLabel();
timeLabel.setHorizontalAlignment(JLabel.CENTER);
statusBar.addRightComponent(timeLabel);
contentPane.add(statusBar, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent event) {
exitProcedure();
}
});
timerThread = new TimerThread(dateLabel, timeLabel);
timerThread.start();
frame.setVisible(true);
}
public void exitProcedure() {
timerThread.setRunning(false);
System.exit(0);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new StatusBarSimulator());
}
public class TimerThread extends Thread {
protected boolean isRunning;
protected JLabel dateLabel;
protected JLabel timeLabel;
protected SimpleDateFormat dateFormat =
new SimpleDateFormat("EEE, d MMM yyyy");
protected SimpleDateFormat timeFormat =
new SimpleDateFormat("h:mm a");
public TimerThread(JLabel dateLabel, JLabel timeLabel) {
this.dateLabel = dateLabel;
this.timeLabel = timeLabel;
this.isRunning = true;
}
#Override
public void run() {
while (isRunning) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Calendar currentCalendar = Calendar.getInstance();
Date currentTime = currentCalendar.getTime();
dateLabel.setText(dateFormat.format(currentTime));
timeLabel.setText(timeFormat.format(currentTime));
}
});
try {
Thread.sleep(5000L);
} catch (InterruptedException e) {
}
}
}
public void setRunning(boolean isRunning) {
this.isRunning = isRunning;
}
}
}
Add a label component at the appropriate place in your JFrame's component hirerarchy (maybe a JToolBar?).
Then create a timer that fires once per second, and add an ActionListener to it that updates the text of the label with the current time.
See the accepted answer at Using SwingWorker and Timer to display time on a label?
Create a SimpleDateFormat object that will help you format the current date. Add a JLabel to your JFrame. In a separate thread, create a loop that keeps reading the current date, format it to a String and pass it to the JLabel in the EDT. Make the separate thread sleep for one second or less before updating the label again.
I am trying to create a swing program. In my program I want to achieve something like this: right click on a panel and select the menu "Draw rectangle" and program should draw a very simple rectangle on the panel. Here is my code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.BevelBorder;
public class MainWindow extends JFrame {
JFrame frame = null;
AboutDialog aboutDialog = null;
JLabel statusLabel = null; //label on statusPanel
public MainWindow() {
frame = new JFrame("Project");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//MENUS
JMenuBar menuBar = new JMenuBar(); //menubar
JMenu menuDosya = new JMenu("Dosya"); //menus on menubar
JMenu menuYardim = new JMenu("Yardım"); //menus in menus
menuBar.add(menuDosya);
menuBar.add(menuYardim);
JMenuItem menuItemCikis = new JMenuItem("Çıkış", KeyEvent.VK_Q); //dosya menus
menuItemCikis.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
System.exit(0);
}
});
menuDosya.add(menuItemCikis);
JMenuItem menuItemYardim = new JMenuItem("Hakkında", KeyEvent.VK_H); //hakkinda menus
menuItemYardim.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
JDialog f = new AboutDialog(new JFrame());
f.show();
}
});
menuYardim.add(menuItemYardim);
frame.setJMenuBar(menuBar);
//TOOLBAR
JToolBar toolbar = new JToolBar();
JButton exitButton = new JButton("Kapat");
toolbar.add(exitButton);
//STATUSBAR
JPanel statusPanel = new JPanel();
statusPanel.setBorder(new BevelBorder(BevelBorder.LOWERED));
frame.add(statusPanel, BorderLayout.SOUTH);
statusPanel.setPreferredSize(new Dimension(frame.getWidth(), 20));
statusPanel.setLayout(new BoxLayout(statusPanel, BoxLayout.X_AXIS));
statusLabel = new JLabel("Ready.");
statusLabel.setHorizontalAlignment(SwingConstants.LEFT);
statusPanel.add(statusLabel);
//MAIN CONTENT OF THE PROGRAM
final JPanel mainContentPanel = new JPanel();
//RIGHT CLICK MENU
final JPopupMenu menuSag = new JPopupMenu("RightClickMenu");
JMenuItem menuRightClickRectangle = new JMenuItem("draw rectangle");
menuRightClickRectangle.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
//CircleShape cs=new CircleShape();
mainContentPanel.add(new CircleShape()); //trying to draw.
mainContentPanel.repaint();
//mainContentPanel.repaint(); boyle olacak.
}
});
JMenuItem menuRightClickCircle = new JMenuItem("Daire çiz");
menuSag.add(menuRightClickRectangle);
menuSag.add(menuRightClickCircle);
mainContentPanel.addMouseListener(new MouseAdapter() {
public void mouseReleased(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON3) {
menuSag.show(e.getComponent(), e.getX(), e.getY());
statusLabel.setText("X=" + e.getX() + " " + "Y=" + e.getY());
}
}
});
JButton west = new JButton("West");
JButton center = new JButton("Center");
JPanel content = new JPanel(); //framein icindeki genel panel. en genel panel bu.
content.setLayout(new BorderLayout());
content.add(toolbar, BorderLayout.NORTH);
content.add(statusPanel, BorderLayout.SOUTH);
content.add(west, BorderLayout.WEST);
content.add(mainContentPanel, BorderLayout.CENTER);
frame.setContentPane(content);
frame.setPreferredSize(new Dimension(400, 300));
frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
}
The problem is nothing is drawn on the panel. I guess there is an event loss in the program but i don't know how to solve this issue.
Please modify the code in the following way. Add a new class like this:
class MainPanel extends JPanel {
private List<Rectangle> rectangles = new ArrayList<Rectangle>();
private void addRectangle(Rectangle rectangle) {
rectangles.add(rectangle);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
for (Rectangle rectangle : rectangles) {
g2.drawRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
}
}
}
Then, instead of
final JPanel mainContentPanel = new JPanel();
you should do:
final MainPanel mainContentPanel = new MainPanel();
And the action listener for the menu item becomes something like this:
menuRightClickRectangle.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
// TODO: add your own logic here, currently a hardcoded rectangle
mainContentPanel.addRectangle(new Rectangle(10, 10, 100, 50));
mainContentPanel.repaint();
}
});
You can't do that by calling add method.To draw a shape you will have to override paintComponent method:
Example of drawing rectangle:
public void paintComponent(Graphics g){
g.setColor(Color.RED);
g.fillRect(50,50,50,50);
}
Hmm did a short example for you:
Test.java:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class Test {
private final JFrame frame = new JFrame();
private final MyPanel panel = new MyPanel();
private void createAndShowUI() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Test().createAndShowUI();
}
});
}
}
MyPanel.java:
class MyPanel extends JPanel {
private final JPopupMenu popupMenu = new JPopupMenu();
private final JMenuItem drawRectJMenu = new JMenuItem("Draw Rectangle here");
private int x = 0, y = 0;
private List<Rectangle> recs = new ArrayList<>();
public MyPanel() {
initComponents();
}
private void initComponents() {
setBounds(0, 0, 600, 600);
setPreferredSize(new Dimension(600, 600));
popupMenu.add(drawRectJMenu);
add(popupMenu);
addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {
checkForTriggerEvent(e);
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
private void checkForTriggerEvent(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON3) {
x = e.getX();
y = e.getY();
popupMenu.show(e.getComponent(), x,y);
}
}
});
drawRectJMenu.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
addRec(new Rectangle(x, y, 100, 100));
repaint();
}
});
}
public void addRec(Rectangle rec) {
recs.add(rec);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
for (Rectangle rec : recs) {
g2d.drawRect(rec.x, rec.y, rec.width, rec.height);
}
}
}
Hi I'm trying to call the paint method every time in a game loop.At the moment the screen pops up with a label and a button once the button has been pressed the label and button go which i want but i can't get the paint method to start i tried j.repaint() & j.validate() neither accessed paint method.Any help would be appreciated.
package sgame;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class SGame extends JPanel
{
public static void main(String[] args)
{
final JFrame window = new JFrame("hello");
final JPanel window1 = new JPanel();
Timer loop = new Timer(1000, new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
GameLoop(window1);
}
});
Window(window, loop);
}
public static void Window(final JFrame window, final Timer loop)
{
final JButton b1 = new JButton("GO!");
b1.setLocation(210, 300);
b1.setSize(70, 50);
window.setVisible(true);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(500, 500);
window.setLocation(420, 170);
window.setBackground(Color.BLACK);
final JLabel Title = new JLabel("Snake", JLabel.CENTER);
Title.setFont(new Font("Times New Roman", Font.ITALIC, 60));
Title.setVerticalAlignment(JLabel.CENTER);
Title.setForeground(Color.WHITE);
window.add(b1);
window.add(Title);
b1.addActionListener(new ActionListener() // runs when buttons pressed
{
#Override
public void actionPerformed(ActionEvent e) // clears header,button and starts timer
{
b1.invalidate();
b1.setVisible(false);
Title.setVisible(false);
Title.invalidate();
loop.start();
}
});
}
public static void GameLoop(JPanel j)
{
// Call paint method
}
public void paintComponent(Graphics g)
{
g.setColor(Color.yellow);
g.drawRect(30, 30, 30, 30);
}
}
The paintComponent() method in SGame is never called because you didn't instanciate any SGame object. And window1 has not been added to the frame.
Something like this should be better :
public class SGame extends JPanel {
private Timer loop;
public SGame(){
loop = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
gameLoop();
}
});
}
public static void main(String[] args) {
final JFrame window = new JFrame("hello");
final JButton b1 = new JButton("GO!");
b1.setLocation(210, 300);
b1.setSize(70, 50);
window.setVisible(true);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(500, 500);
window.setLocation(420, 170);
window.setBackground(Color.BLACK);
final JLabel Title = new JLabel("Snake", JLabel.CENTER);
Title.setFont(new Font("Times New Roman", Font.ITALIC, 60));
Title.setVerticalAlignment(JLabel.CENTER);
Title.setForeground(Color.WHITE);
window.add(b1);
window.add(Title);
b1.addActionListener(new ActionListener() { // runs when buttons pressed
#Override
public void actionPerformed(ActionEvent e) // clears header,button
{
b1.invalidate();
b1.setVisible(false);
Title.setVisible(false);
Title.invalidate();
SGame sg = new SGame();
window.add(sg);
sg.start();
}
});;
}
public void start(){
loop.start();
}
public void gameLoop() {
repaint();
}
#Override
public void paintComponent(Graphics g) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.yellow);
g.drawRect(30, 30, 30, 30);
}
}