I need help with drawing the grids to the GUI as well as the program later letting me change the colour of the boxes drawn. I know i will have to use paintComponent(Graphics g), but i have no idea how or where.
So here is a copy of the code i have got so far ( even though i have been told it can be quite daunting just being given code i think it is the best way for people to help and not just do it for me). From the top it sets values, creates the GUI, calls the GUI, fills a 2d array with boxes( i think). Then in the Boxes class setting values the boxes class will need, then the start of how to draw them (didn't know how to work it out), then some seta methods for the x and y coordinates.
what i would like you to do is show how to have the boxes be drawn to the Jpanel, to make a grid and then to show me how to change the colour to different shades of blue, depending on a external value.
import java.awt.*;
import java.awt.Graphics;
import java.util.*;
import javax.swing.*;
public class NewGrid {
Boxes[][] Boxs;
int BoxesX;
int BoxesY;
NewGrid() {
buildtheGUI();
}
JFrame frame = new JFrame();
JPanel panel = new JPanel();
public void buildtheGUI() {
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.setVisible(true);
}
public static void main(String[] args) {
new NewGrid();
}
public void addboxes() {
Boxs = new Boxes[panel.getWidth() / 10][panel.getHeight() / 10];
for (int i = 0; i < panel.getWidth() / 10; i++) {
for (int j = 0; j < panel.getHeight() / 10; j++) {
Boxs[i][j] = new Boxes();
Boxs[i][j].setx(i * (panel.getWidth() / 10));
Boxs[i][j].sety(j * (panel.getHeight() / 10));
Boxs[i][j].draw(null);
}
}
}
}
public class Boxes extends JPanel {
int x;
int y;
int width = 10;
int hieight = 10;
Color colour = Color.BLACK;
public void draw(Graphics g) {
g.setColor(colour);
g.fillRect(x, y, width, hieight);
}
public void setx(int i ){
x = i;
}
public void sety(int i ){
y = i;
}
}
I can't comment something, to try to make things easier,
I code there box.putClientProperty(unique_identifier, value_for_identifier), you can to multiple this method as you want
from every Swing Listener you can to get this and proper coordinated defined in putClientProperty
.
JComponent comp = event.getComponent();
String strRow = (String) comp.getClientProperty("row");
String strColumn = (String) comp.getClientProperty("column");
simple code
import java.awt.*;
import java.awt.Graphics;
import java.util.*;
import javax.swing.*;
public class NewGrid {
private int row = 10;
private int column = 10;
private JFrame frame = new JFrame();
private JPanel panel = new JPanel();
private NewGrid() {
addboxes();
panel.setLayout(new GridLayout(row, column));
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
private void addboxes() {
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
Boxes box = new Boxes();
box.putClientProperty("row", row);
box.putClientProperty("column", column);
panel.add(box);
}
}
}
public static void main(String[] args) {
Runnable doRun = new Runnable() {
#Override
public void run() {
new NewGrid();
}
};
SwingUtilities.invokeLater(doRun);
}
}
class Boxes extends JPanel {
private static final long serialVersionUID = 1L;
#Override
public Dimension getMinimumSize() {
return new Dimension(20, 20);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(20, 20);
}
#Override
public Dimension getMaximumSize() {
return new Dimension(20, 20);
}
#Override
public void paintComponent(Graphics g) {
int margin = 2;
Dimension dim = getSize();
super.paintComponent(g);
g.setColor(Color.red);
g.fillRect(margin, margin, dim.width - margin * 2,
dim.height - margin * 2);
}
}
Related
When a Grid Object is instantiated, a JFrame and JPanel are created. Lines are drawn upon the JPanel to create a square grid. Ideally, the grid will scale if the window is resized.
import javax.swing.JPanel;
import javax.swing.JFrame;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.event.ComponentListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentAdapter;
public class Grid {
private int lines;
private int space;
public static final int DEFAULT_LINES = 5;
public static final int DEFAULT_SPACE = 5;
private JPanel panel = new GridPanel();
private JFrame frame;
public Grid(String name, int lines, int space) {
this.frame = new JFrame(name);
this.lines = lines;
this.space = space;
this.frame.setSize((lines * space), (lines * space));
}
private class GridPanel extends JPanel {
private int start = 0;
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
int end = (lines * space);
g.setColor(Color.BLACK);
for (int i = 0; i < lines; i++) {
int crawl = (space * i);
g.drawLine(start, crawl, end, crawl);
g.drawLine(crawl, start, crawl, end);
}
}
}
/*private class GridHandler extends ComponentAdapter {
#Override
public void componentResized(ComponentEvent e) {
super.componentResized(e);
setSpace();
frame.repaint();
frame.revalidate();
}
}*/
public void setSpace() {
space = (frame.getSize().width * frame.getSize().height) / lines;
}
public void run() {
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(panel);
//frame.addComponentListener(new GridHandler());
frame.setVisible(true);
}
}
public class Run {
public static final int ONE_LINES = 15;
public static final int ONE_SPACE = 20;
public static final int TWO_LINES = 35;
public static final int TWO_SPACE = 16;
public static void main(String[] args) {
Grid grid1 = new Grid("Grid One", ONE_LINES, ONE_SPACE);
Grid grid2 = new Grid("Grid Two", TWO_LINES, TWO_SPACE);
grid1.run();
grid2.run();
}
}
These are the only two files being used. The Handler is currently commented out, and the code does what is expected. Two windows with grids are created. However, when the handler is implemented, the grid no longer shows up. What is the correct implementation for the handler?
For anyone that cares, this is a viable solution. As it turns out, a componentResized Event Handler is not needed. The paintComponent is automatically executed when the JFrame is re-sized.
The following code creates two separate JFrames. Each JFrame contains a single JPanel. A unique square grid is drawn on the JPanel. If the JFrame is re-sized, the grid will also re-size (while still remaining square).
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.*;
public class Grid extends JPanel {
private static final int DEFAULT_COUNT = 10;
private static final int DEFAULT_SIZE = 100;
private int count;
public Grid(int count, int size) {
if (size < 1) {
this.count = DEFAULT_COUNT;
this.setPreferredSize(new Dimension(DEFAULT_SIZE, DEFAULT_SIZE));
} else {
this.count = count;
this.setPreferredSize(new Dimension(size, size));
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D graphics = (Graphics2D) g;
graphics.setColor(Color.black);
Dimension size = getSize();
int w = size.width;
int h = size.height;
if (w > h) {
w = h;
} else if (h > w) {
h = w;
}
int spaceWidth = (int)((double)w / count);
int spaceHeight = (int)((double)h / count);
for (int row = 0; row <= count; row++) {
int y = (row * spaceHeight);
int x = (row * spaceWidth);
graphics.drawLine(0, y, (spaceWidth * count), y);
graphics.drawLine(x, 0, x, (spaceHeight * count));
}
}
}
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.*;
public class Test {
public static final int COUNT_1 = (-5);
public static final int SIZE_1 = 4;
public static final int COUNT_2 = 35;
public static final int SIZE_2 = 16;
public static void main(String[] args) {
int area1 = COUNT_1 * SIZE_1;
int area2 = COUNT_2 * SIZE_2;
Grid grid = new Grid(COUNT_1, area1);
JFrame frame = new JFrame("Grid");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(grid);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Grid grid2 = new Grid(COUNT_2, area2);
JFrame frame2 = new JFrame("Grid");
frame2.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame2.add(grid2);
frame2.pack();
frame2.setLocationRelativeTo(null);
frame2.setVisible(true);
}
}
Hello guys I am currently having problems with making anything show with my paint component. I have tried numerous things that I have seen online and tried a lot of different things myself but i Just can't get it to show anything. I am trying to get my paint component to show a series of bars that move as an array being sorted using swing but i can't even get it ti show anything. Any help would be appreciated.
package proj2;
import java.awt.*;
import java.awt.event.*;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingWorker;
public class project2 extends JFrame
{
private JButton button1 = new JButton("Insertion");
private UpdateTextFieldThread currentThread;
private int[] array = new int[15];
private Display display;
private class ButtonHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
Object src = e.getSource();
if (src == button1){
insertionSort(array);
(new UpdateTextFieldThread()).execute();
}
}
}
public project2()
{
setTitle("Sorting Charts");
setSize(400,250);
setDefaultCloseOperation(EXIT_ON_CLOSE);
for(int i=0; i<array.length;i++)
array[i]=(int) (Math.random()*100);
display=new Display();
ButtonHandler bh = new ButtonHandler();
button1.addActionListener(bh);
JPanel container = new JPanel();
container.setLayout(new GridLayout(2, 2));
container.add(button1);
JPanel masterPanel=new JPanel();
masterPanel.setLayout(new BorderLayout());
masterPanel.add(display, BorderLayout.SOUTH);
masterPanel.add(container, BorderLayout.NORTH);
setContentPane(container);
setVisible(true);
display.repaint();
}
private class Display extends JPanel {
private Color color = Color.RED;
//#Override
public void paintComponent(Graphics g) {
super.paintComponents(g);
g.setColor(Color.RED);
Dimension d = getSize();
int clientWidth = d.width;
int clientHeight = d.height;
int barWidth = clientWidth / array.length;
for(int i=0;i<array.length;i++){
int x=0;
int y=15;
int linethickness=5;
int linelength=10;
g.setColor(Color.red);
g.fillRect(x, clientHeight, linelength*array[i] , linethickness);
g.setColor(Color.black);
g.drawRect(x,clientHeight, linelength*array[i], linethickness);
x+=15;
}
}
}
private class UpdateTextFieldThread extends SwingWorker<Void, Integer>
{
protected Void doInBackground()
{
display.repaint();
return null;
//should have repaint method in here somewhere
/*for (int i = 0; i < 50; i++) {
publish(i);
try {
Thread.sleep(THREAD_DELAY);
} catch (InterruptedException e) { }
}
return null;*/
}
// The parameter here is a list of all published data
// since the last call to process. We are interested
// in displaying only the latest one on the GUI.
protected void process(java.util.List<Integer> list)
{
// textfield.setText("" + list.get(list.size() - 1));
}
}
public static <T extends Comparable<T>> void insertionSort(int[] hue2)
{
for (int i = 1; i < hue2.length; i++) {
int thingToInsert = hue2[i];
int j = i - 1;
while (j >= 0 && thingToInsert<hue2[j]) {
hue2[j+1] = hue2[j];
j--;
}
hue2[j+1] = thingToInsert;
}
}
public static void main(String[]args) {
new project2();
}
}
masterPanel.add(display, BorderLayout.SOUTH);
You are adding your Display panel to the SOUTH of a BorderLayout. The SOUTH constraint will respsect the preferred height of the component. Your component has a height of 0, to there is nothing to display.
Whenever you do custom painting you also need to override the getPreferredSize() method of the component to provide the appropriate size of the component so the layout managers can do there job.
The panel doesn't fit in the frame, and when I change the size of the frame a new panel is painted. I want the panel to fit and also to change the size on the frame without painting a new panel.
Here is the code:
import java.awt.*;
import javax.swing.*;
public class ColorGrid extends JPanel {
int length=200;
int width=200;
double stokastik;
public ColorGrid(int x,int y) {
setSize(200,200);
width=18*x;
length=18*y;
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
for(int row=0; row <=length;row+=20) {
for(int col=0; col <=width;col+=20) {
stokastik= Math.random();
if(stokastik < 0.25){
g.setColor(Color.YELLOW);
}
else if (stokastik < 0.5) {
g.setColor(Color.BLUE);
}
else if (stokastik < 0.75) {
g.setColor(Color.GREEN);
} else {
g.setColor(Color.RED);
}
g.fillRect(row, col, 18, 18);
}
}
}
public static void main(String args[]) {
JFrame frame = new JFrame();
frame.setBounds(300,300,300,300);
ColorGrid grid = new ColorGrid(10,10);
frame.add(grid);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
}
}
Your code is confusing because you call setBounds/setSize, but eventually, you call pack() which will just resize everything according to preferred size of components.
The proper way to go is to override getPreferredSize() in your custom component. By all means, avoid calling setSize/setBounds/setLocation. This is the job of the LayoutManager.
Regarding the repaint of the panel, you don't have a choice. A panel can get repainted many times independently of your will. So the only way to avoid the change of colors when the repaint occurs, is to pre-calculate the colors upfront and then only iterate over the same colors when performing the custom painting.
Small demo code illustrating this:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ColorGrid extends JPanel {
double stokastik;
private int width;
private int length;
private Dimension preferredSize;
private Color[][] colors;
public ColorGrid(int x, int y) {
width = 20 * x;
length = 20 * y;
preferredSize = new Dimension(width, length);
colors = new Color[x][y];
for (int row = 0; row < x; row++) {
for (int col = 0; col < y; col++) {
stokastik = Math.random();
if (stokastik < 0.25) {
colors[row][col] = (Color.YELLOW);
} else if (stokastik < 0.5) {
colors[row][col] = (Color.BLUE);
} else if (stokastik < 0.75) {
colors[row][col] = (Color.GREEN);
} else {
colors[row][col] = (Color.RED);
}
}
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int row = 0; row < colors.length; row++) {
for (int col = 0; col < colors[row].length; col++) {
g.setColor(colors[row][col]);
g.fillRect(row * 20, col * 20, 18, 18);
}
}
}
#Override
public Dimension getPreferredSize() {
return preferredSize;
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ColorGrid grid = new ColorGrid(10, 10);
frame.add(grid);
frame.pack();
frame.setVisible(true);
}
});
}
}
In your constructor set the preferred size.
public ColorGrid(int x, int y) {
setSize(200, 200);
setPreferredSize(new Dimension(200, 200));
width = 18 * x;
length = 18 * y;
}
Then it will show correctly on initial load..
As mentioned by another answer, also have your length and width defined proportionally.
http://www.youtube.com/watch?v=M0cNsmjK33E
I want to develop something similar to the link above using Java Swing. I have the sorting method and did while repaint but when I triggered the sorting, instead of showing the bars slowly sorting itself, it freezes and then unfreezes when the array has been fully sorted.
How do I fix this?
Edit: sorry forgot about the codes. its a very simple gui. and another class for sorting which sorts the whole array
public class SortGUI {
JFrame frame;
int frameWidth = 1000, frameHeight = 1000;
int panelWidth, panelHeight;
DrawPanel panel;
JPanel panel2;
JScrollPane scroll;
JViewport view;
static int[] S = new int[50000];
public static void main(String[] args) throws InterruptedException {
SortGUI app = new SortGUI();
initializeArray();
app.go();
}
public static void initializeArray()
{
for (int i = 0; i < S.length; i++) {
S[i] = (int) (Math.random() * 16581375);
}
}
public void go() throws InterruptedException {
//Frame
frame = new JFrame();
frame.setSize(frameWidth, frameHeight);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//panel
panel = new DrawPanel();
scroll = new JScrollPane(panel,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
//Layout
frame.add(scroll);
frame.addKeyListener(new keyListener());
while(true)
{
panel.repaint();
}
}
public class DrawPanel extends JPanel
{
public DrawPanel()
{
this.setPreferredSize(new Dimension(50000,930));
}
public void paintComponent(Graphics g)
{
g.setColor(Color.WHITE);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
for(int i = 0; i < S.length; i++)
{
int red = S[i] / 65025;
int green = (S[i] > 65025)? S[i] % 65025 : 0;
int blue = green;
blue %= 255;
green /= 255;
g.setColor(new Color(red,green,blue));
g.fillRect(i, 900 - (S[i] / 18500), 1, S[i] / 18500);
}
}
}
public class keyListener implements KeyListener{
public void keyTyped(KeyEvent ke) {
}
public void keyPressed(KeyEvent ke) {
if(ke.getKeyChar() == '1')
{
sorter.bubbleSort(S);
}
}
public void keyReleased(KeyEvent ke) {
}
}
}
Note: I started writing this before the question was deleted
Most likely your using some looping mechanism and praying that each iteration, the ui with be updated. That's a wrong assumption. The UI will not be update until the loop is finished. What you are doing is what we refer to as blocking the Event Dispatch Thread(EDT)
See How to use a Swing Timer. Make "iterative" updates in the ActionListener call back. For instance, if you want to animate a sorting algorithm, you need to determine what needs to be updated per "iteration" of the timer callback. Then each iteration repaint the ui.
So your Timer timer could look something like
Timer timer = new Timer(40, new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
if (sortingIsDone()) {
((Timer)e.getSource()).stop();
} else {
sortOnlyOneItem();
}
repaint();
}
});
Your sortOnlyOneItem method should only, well, perform a sort for just one item. And have some sort of flag to check if the sorting is done, then stop the timer.
Other notes:
You should be calling super.paintComponent in the paintComponent method, if you aren't going to paint the background yourself. Generally I always do though.
Here's a complete example. I'm glad you figured it out on your own. I was working on this example before I saw that you got it.
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.Collections;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class SelectionSortAnimate extends JPanel {
private static final int NUM_OF_ITEMS = 20;
private static final int DIM_W = 400;
private static final int DIM_H = 400;
private static final int HORIZON = 350;
private static final int VERT_INC = 15;
private static final int HOR_INC = DIM_W / NUM_OF_ITEMS;
private JButton startButton;
private Timer timer = null;
private JButton resetButton;
Integer[] list;
int currentIndex = NUM_OF_ITEMS - 1;
public SelectionSortAnimate() {
list = initList();
timer = new Timer(200, new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (isSortingDone()) {
((Timer) e.getSource()).stop();
startButton.setEnabled(false);
} else {
sortOnlyOneItem();
}
repaint();
}
});
startButton = new JButton("Start");
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
timer.start();
}
});
resetButton = new JButton("Reset");
resetButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
list = initList();
currentIndex = NUM_OF_ITEMS - 1;
repaint();
startButton.setEnabled(true);
}
});
add(startButton);
add(resetButton);
}
public boolean isSortingDone() {
return currentIndex == 0;
}
public Integer[] initList() {
Integer[] nums = new Integer[NUM_OF_ITEMS];
for (int i = 1; i <= nums.length; i++) {
nums[i - 1] = i;
}
Collections.shuffle(Arrays.asList(nums));
return nums;
}
public void drawItem(Graphics g, int item, int index) {
int height = item * VERT_INC;
int y = HORIZON - height;
int x = index * HOR_INC;
g.fillRect(x, y, HOR_INC, height);
}
public void sortOnlyOneItem() {
int currentMax = list[0];
int currentMaxIndex = 0;
for (int j = 1; j <= currentIndex; j++) {
if (currentMax < list[j]) {
currentMax = list[j];
currentMaxIndex = j;
}
}
if (currentMaxIndex != currentIndex) {
list[currentMaxIndex] = list[currentIndex];
list[currentIndex] = currentMax;
}
currentIndex--;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < list.length; i++) {
drawItem(g, list[i], i);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(DIM_W, DIM_H);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("Sort");
frame.add(new SelectionSortAnimate());
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
I have a problem in my application using line primitives and JLables. I try to explain it:
I have to draw a vehicle route using lines to represent roads and JLabels to represent cities. I need the use of JLabels because each JLabel has a Listener that shows a dialog with information about the city.
I redefine paint() method of my main JPanel. In that method I first in invoke the super.paint(), then I draw the lines and finally I add the Labels to the JPanel.
The problem is that the lines overlap the labels regardless the matter the order of painting them. Is there any suggestion?
You can also override paintComponent() or paintChildren() methods of the JPanel.
In the paintChildren() call your lines drawing and then super to draw JLabels.
anothe way should be
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class AddVertexDemo {
public AddVertexDemo() {
}
private static void createAndShowUI() {
JFrame frame = new JFrame("AddVertexDemo");
frame.getContentPane().add(new Gui().getMainPanel());
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() {
#Override
public void run() {
createAndShowUI();
}
});
}
}
class DrawingPanel extends JPanel {
private static final int RADIUS = 6;
private static final long serialVersionUID = 1L;
private List<Shape> vertexList = new ArrayList<Shape>();
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
if (vertexList.size() > 1) {
Shape s0 = vertexList.get(0);
Shape s1 = null;
for (int i = 0; i < vertexList.size(); i++) {
s1 = vertexList.get(i);
drawConnectingLine(g, s0, s1);
s0 = s1;
}
s1 = vertexList.get(0);
//drawConnectingLine(g2, s0, s1);
}
for (Shape shape : vertexList) {
g2.setColor(Color.blue);
g2.fill(shape);
g2.setColor(Color.blue.darker().darker());
g2.draw(shape);
}
}
private void drawConnectingLine(Graphics g, Shape s0, Shape s1) {
Rectangle r0 = s0.getBounds();
Rectangle r1 = s1.getBounds();
int x0 = r0.x + r0.width / 2;
int y0 = r0.y + r0.height / 2;
int x1 = r1.x + r1.width / 2;
int y1 = r1.y + r1.height / 2;
g.drawLine(x0, y0, x1, y1);
}
public void addVertex(Point p) {
int x = p.x - RADIUS;
int y = p.y - RADIUS;
int w = 2 * RADIUS;
int h = w;
vertexList.add(new Ellipse2D.Double(x, y, w, h));
repaint();
}
public void removeVertex(Point p) {
if (vertexList.size() > 0) {
for (int i = vertexList.size() - 1; i >= 0; i--) {
if (vertexList.get(i).contains(p)) {
vertexList.remove(i);
repaint();
return;
}
}
}
}
}
class Gui {
private static final Dimension DRAWING_PANEL_SIZE = new Dimension(600, 500);
private JPanel mainPanel = new JPanel(new BorderLayout());
private DrawingPanel drawingPanel = new DrawingPanel();
private JToggleButton addVertexBtn = new JToggleButton("Add Vertex");
private JToggleButton removeVertexBtn = new JToggleButton("Remove Vertex");
Gui() {
JPanel buttonPanel = new JPanel();
buttonPanel.add(addVertexBtn);
buttonPanel.add(removeVertexBtn);
DrawPanelMouseListener mouseListener = new DrawPanelMouseListener();
mouseListener.setDrawingPanel(drawingPanel);
mouseListener.setGui(this);
drawingPanel.addMouseListener(mouseListener);
drawingPanel.setPreferredSize(DRAWING_PANEL_SIZE);
drawingPanel.setBorder(BorderFactory.createLineBorder(Color.black));
mainPanel.add(drawingPanel, BorderLayout.CENTER);
mainPanel.add(buttonPanel, BorderLayout.SOUTH);
}
public JPanel getMainPanel() {
return mainPanel;
}
public boolean isAddingVertex() {
return addVertexBtn.isSelected();
}
public boolean isRemovingVertex() {
return removeVertexBtn.isSelected();
}
public void setAddingVertex(boolean addingVertex) {
addVertexBtn.setSelected(addingVertex);
}
public void setRemovingVertex(boolean removingVertex) {
removeVertexBtn.setSelected(removingVertex);
}
}
class DrawPanelMouseListener extends MouseAdapter {
private DrawingPanel drawingPanel;
private Gui gui;
public DrawPanelMouseListener() {
}
public void setGui(Gui gui) {
this.gui = gui;
}
public void setDrawingPanel(DrawingPanel drawingPanel) {
this.drawingPanel = drawingPanel;
}
#Override
public void mousePressed(MouseEvent me) {
if (gui.isAddingVertex() && gui.isRemovingVertex()) {
gui.setAddingVertex(false);
gui.setRemovingVertex(false);
return;
}
if (gui.isAddingVertex()) {
drawingPanel.addVertex(me.getPoint());
gui.setAddingVertex(false);
}
if (gui.isRemovingVertex()) {
drawingPanel.removeVertex(me.getPoint());
gui.setRemovingVertex(false);
}
}
}
I'm not sure that this is the right way to do this but you can try this:
Create 2 panels. One for drawing lines and another for drawing buildings(labels).
Add both panels in LayeredPane of JFrame. Add panel with line in lower layer then panel with labels.
You can use LayeredPanes in other ways also to solve your problem. Learn more here: How to use Layered Panes in java