I'm actually stuck on something strange. I have a JFrame with a JScrollPane containing a jPanel far larger than the actual screen. I draw squares in colums and I want theses squares to go over the right border of the jPanel. (So that they will appear as you scroll to the right.) But the squares painted with the method paintComponents just stop at the visible ViewPort of the JScrollPane.
Here is my code for the JScrollPane inside of the JFrame:
public void initComponents(){
mainPanel = new DrawPanel(dim);
this.getContentPane().setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridheight = 1;
gbc.gridwidth = 1;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weighty = 1;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.BOTH;
JScrollPane jsp = new JScrollPane(mainPanel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
jsp.setLayout(new ScrollPaneLayout());
jsp.setViewportView(mainPanel);
jsp.getVerticalScrollBar().setUnitIncrement(20);
jsp.setBorder(BorderFactory.createEmptyBorder());
jsp.setPreferredSize(new Dimension(dim.width,dim.height -taskBarSize));
jsp.setMinimumSize(new Dimension(dim.width,dim.height -taskBarSize));
jsp.setMaximumSize(new Dimension(dim.width,dim.height -taskBarSize));
this.getContentPane().add(jsp, gbc);
this.getContentPane().revalidate();
this.getContentPane().repaint();
}
And here is my JPanel class :
public class DrawPanel extends JPanel {
private Dimension dim;
private Integer numberPanels = 7;
private Double startPointX;
private Double startPointY;
private Double heightRow;
private Double heightPanel;
public DrawPanel(Dimension d) {
this.dim = d;
//this.setBackground(Color.BLACK);
calculateStartPoint();
}
public void calculateStartPoint() {
startPointX = (dim.getWidth() / 10) * 1;
startPointY = (dim.getHeight() / 10) * 1;
heightRow = (dim.getHeight() * 0.8) / numberPanels;
heightPanel = heightRow - 10;
double colums = 366/numberPanels;
this.setPreferredSize(new Dimension((int)(heightRow *((int)colums + 1)), dim.height ));
this.setMinimumSize(new Dimension((int)(heightRow *((int)colums + 1)), dim.height ));
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GRAY);
for (int i = 1; i <= 366; i++) {
// Si c'est le dernier d'une colonne
if (i%numberPanels == 0 && i != 0) {
g.fillRect(startPointX.intValue(), startPointY.intValue(), heightPanel.intValue(),
heightPanel.intValue());
startPointX = startPointX + heightRow;
startPointY = startPointY - ((numberPanels -1) * heightRow);
// Si c'est encore dans la meme colonne
} else {
g.fillRect(startPointX.intValue(), startPointY.intValue(), heightPanel.intValue(),
heightPanel.intValue());
startPointY = startPointY + heightRow;
}
}
}
}
At startup:
When I move the scrollPane:
Also, on resizing everything disapreas. Also I had to see that when scrolling back, the already painted squares disapeared, as if everything out of screen disppears.
Thanks for anybody who has some time for this.
Your problem is that you need to recalculate the starting points every time the painting is done. Else the variables keep increasing unnecessarily. So add two lines:
#Override
protected void paintComponent(Graphics g) { // should be protected
super.paintComponent(g);
// need to re-initialize variables within this
startPointX = (dim.getWidth() / 10) * 1;
startPointY = (dim.getHeight() / 10) * 1;
FYI, in the future, please post a MCVE with your question. For example, this is the MCVE that I made out of your code, code that now can be copied, pasted and run by anyone:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.*;
#SuppressWarnings("serial")
public class Foo02 extends JPanel {
private DrawPanel mainPanel;
private Dimension dim = new Dimension(200, 200);
public Foo02() {
initComponents();
}
public void initComponents() {
mainPanel = new DrawPanel(dim);
// !! this.getContentPane().setLayout(new GridBagLayout());
setLayout(new GridBagLayout()); // !!
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridheight = 1;
gbc.gridwidth = 1;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weighty = 1;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.BOTH;
JScrollPane jsp = new JScrollPane(mainPanel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
jsp.setLayout(new ScrollPaneLayout());
jsp.setViewportView(mainPanel);
jsp.getVerticalScrollBar().setUnitIncrement(20);
jsp.setBorder(BorderFactory.createEmptyBorder());
jsp.setPreferredSize(new Dimension(dim.width, dim.height));
jsp.setMinimumSize(new Dimension(dim.width, dim.height));
jsp.setMaximumSize(new Dimension(dim.width, dim.height));
add(jsp, gbc);
revalidate();
repaint();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui() {
Foo02 mainPanel = new Foo02();
JFrame frame = new JFrame("Foo02");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}
#SuppressWarnings("serial")
class DrawPanel extends JPanel {
private Dimension dim;
private Integer numberPanels = 7;
private Double startPointX;
private Double startPointY;
private Double heightRow;
private Double heightPanel;
public DrawPanel(Dimension d) {
this.dim = d;
// this.setBackground(Color.BLACK);
calculateStartPoint();
}
public void calculateStartPoint() {
startPointX = (dim.getWidth() / 10) * 1;
startPointY = (dim.getHeight() / 10) * 1;
heightRow = (dim.getHeight() * 0.8) / numberPanels;
heightPanel = heightRow - 10;
double colums = 366 / numberPanels;
this.setPreferredSize(new Dimension((int) (heightRow * ((int) colums + 1)), dim.height));
this.setMinimumSize(new Dimension((int) (heightRow * ((int) colums + 1)), dim.height));
}
#Override
protected void paintComponent(Graphics g) { // should be protected
super.paintComponent(g);
// need to re-initialize variables within this
startPointX = (dim.getWidth() / 10) * 1;
startPointY = (dim.getHeight() / 10) * 1;
g.setColor(Color.GRAY);
for (int i = 1; i <= 366; i++) {
// Si c'est le dernier d'une colonne
if (i % numberPanels == 0 && i != 0) {
g.fillRect(startPointX.intValue(), startPointY.intValue(), heightPanel.intValue(),
heightPanel.intValue());
startPointX = startPointX + heightRow;
startPointY = startPointY - ((numberPanels - 1) * heightRow);
// Si c'est encore dans la meme colonne
} else {
g.fillRect(startPointX.intValue(), startPointY.intValue(), heightPanel.intValue(),
heightPanel.intValue());
startPointY = startPointY + heightRow;
}
}
}
}
Related
I have been trying very hard these past days to understand Graphics2d. I do understand the shapes an all, however I can not draw a simple Graph with it.
My Goal is to draw a Coordinate System, that you can change its length if you want to. Like you say the min x Value would be -5 and the max x Value would be 10 and it would scale it self to it and the function too. However I have a really big Problem just creating and scaling the axis correctly. I think this just comes from a high not understanding everything correctly. This is why I would be glad if someone could help me with this matter.
Here is the code I have been working on. It is absolutely not finished. However I would like to get the scaling and all right. But ever other correction is gladly welcomed, due to me being a newbie in java.
I also tried to make it that if like min x would be positive there would be no x axis. Which just does not work.
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
public class GraphPlotter extends JFrame {
//f(x) = ax² + bx + c
//Knöpfe
private JButton _ploten = new JButton("Plot");
private JButton _limits = new JButton("Limits");
//Text
private JLabel _funk = new JLabel("f(x) =");
private JLabel _x2 = new JLabel("x² +");
private JLabel _x = new JLabel("x +");
private JLabel _xmin = new JLabel("X min");
private JLabel _ymin = new JLabel("Y min");
private JLabel _ymax = new JLabel("Y max");
private JLabel _xmax = new JLabel("X max");
private String _nummber = "0";
//Textfelder
private JTextField _a = new JTextField(_nummber, 3);
private JTextField _b = new JTextField(_nummber, 3);
private JTextField _c = new JTextField(_nummber, 3);
private JTextField _xMinField = new JTextField("-10");
private JTextField _xMaxField = new JTextField("10");
private JTextField _yMinField = new JTextField("-10");
private JTextField _yMaxField = new JTextField("10");
//Felder
private JPanel _top = new JPanel();
private JPanel _zoom = new JPanel();
private JPanel _graph = new Graph();
public GraphPlotter() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(500, 500);
setTitle("Graph Plotter");
//Alignment
_funk.setAlignmentX(Component.CENTER_ALIGNMENT);
_x2.setAlignmentX(Component.CENTER_ALIGNMENT);
_x.setAlignmentX(Component.CENTER_ALIGNMENT);
_ploten.setAlignmentX(Component.CENTER_ALIGNMENT);
_a.setAlignmentX(Component.CENTER_ALIGNMENT);
_b.setAlignmentX(Component.CENTER_ALIGNMENT);
_c.setAlignmentX(Component.CENTER_ALIGNMENT);
//So if you click on the TextField that it marks it
_a.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent fe) {
_a.setSelectionStart(0);
_a.setSelectionEnd(_a.getText().length());
}
});
_b.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent fe) {
_b.setSelectionStart(0);
_b.setSelectionEnd(_b.getText().length());
}
});
_c.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent fe) {
_c.setSelectionStart(0);
_c.setSelectionEnd(_c.getText().length());
}
});
_xMinField.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent fe) {
_xMinField.setSelectionStart(0);
_xMinField.setSelectionEnd(_xMinField.getText().length());
}
});
_xMaxField.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent fe) {
_xMaxField.setSelectionStart(0);
_xMaxField.setSelectionEnd(_xMaxField.getText().length());
}
});
_yMinField.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent fe) {
_yMinField.setSelectionStart(0);
_yMinField.setSelectionEnd(_yMinField.getText().length());
}
});
_yMaxField.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent fe) {
_yMaxField.setSelectionStart(0);
_yMaxField.setSelectionEnd(_yMaxField.getText().length());
}
});
//Aktions for the buttons
_ploten.addActionListener(new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
//draw a new function
}
});
_limits.addActionListener(new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
//reskale the Graph
}
});
//Layouts
//Main
setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.FIRST_LINE_START;
c.fill = GridBagConstraints.HORIZONTAL;
c.ipady = 20;
c.gridwidth = 3;
c.gridx = 0;
c.gridy = 0;
add(_top, c);
c.anchor = GridBagConstraints.FIRST_LINE_START;
c.fill = GridBagConstraints.BOTH;
c.weightx = 1.0;
c.gridwidth = 2;
c.gridx = 0;
c.gridy = 1;
add(_graph, c);
c.anchor = GridBagConstraints.FIRST_LINE_END;
c.fill = GridBagConstraints.VERTICAL;
c.weightx = 0.0;
c.weighty = 0.5;
c.ipadx = 20;
c.gridwidth = 1;
c.gridx = 2;
c.gridy = 1;
add(_zoom, c);
//Skalling
_zoom.setLayout(new BoxLayout(_zoom, BoxLayout.PAGE_AXIS));
//Borders to better see the layout
_top.setBorder(BorderFactory.createStrokeBorder(new BasicStroke(5.0f)));
_graph.setBorder(BorderFactory.createStrokeBorder(new BasicStroke(5.0f)));
_zoom.setBorder(BorderFactory.createStrokeBorder(new BasicStroke(5.0f)));
_top.add(_funk);
_top.add(_a);
_top.add(_x2);
_top.add(_b);
_top.add(_x);
_top.add(_c);
_top.add(_ploten);
_zoom.add(_xmin);
_zoom.add(_xMinField);
_zoom.add(_xmax);
_zoom.add(_xMaxField);
_zoom.add(_ymin);
_zoom.add(_yMinField);
_zoom.add(_ymax);
_zoom.add(_yMaxField);
_zoom.add(_limits);
setVisible(true);
}
public class Graph extends JPanel {
Color[] _color = {Color.RED, Color.BLUE, Color.GREEN, Color.YELLOW, Color.MAGENTA, Color.CYAN, Color.ORANGE, Color.PINK};
int c = 0;
int _width;
int _hight;
int _diffX;
int _diffY;
int _midx;
int _midy;
int xMAX;
int xMIN;
int yMAX;
int yMIN;
public void paintComponent(Graphics g) {
_width = getWidth();
_hight = getHeight();
//Max und Min
xMAX = Integer.parseInt(_xMaxField.getText());
xMIN = Integer.parseInt(_xMinField.getText());
yMAX = Integer.parseInt(_yMaxField.getText());
yMIN = Integer.parseInt(_yMinField.getText());
//Diff
_diffX = xMAX + xMIN;
_diffY = yMAX + yMIN;
if (!(xMIN > 0) && !(xMAX < 0)) {
_midx = (_width / 2) - _diffX;
} else {
_midx = 0;
}
if (!(yMIN > 0) && !(yMAX < 0)) {
_midy = (_hight /2) - _diffY;
} else {
_midy = 0;
}
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g;
drawAxis(g2D);
}
private void drawAxis(Graphics2D g2d) {
g2d.setColor(Color.BLACK);
g2d.setStroke(new BasicStroke(2));
//X-Achse
if (!(xMIN > 0) && !(xMAX < 0)) {
g2d.drawLine(0, _midy, _width, _midy);
}
//Y-Achse
if (!(yMIN > 0) && !(yMAX < 0)) {
g2d.drawLine(_midx, 0, _midx, _hight);
}
//Scales drawing
g2d.setStroke(new BasicStroke(1));
for (int n = 0; n < _width; n = n + 5) {
g2d.drawLine(n + _midx, _midy, n + _midx, _midy + 5);
g2d.drawLine(n - _midx, _midy, n - _midx, _midy + 5);
}
for (int n = 0; n < _hight; n = n +5) {
g2d.drawLine(_midx, n + _midy, _midx - 5, n + _midy);
g2d.drawLine(_midx, n - _midy, _midx - 5, n - _midy);
}
}
private void drawGraph(Graphics2D g2d) {
if (!(Integer.parseInt(_a.getText()) == 0) && !(Integer.parseInt(_b.getText()) == 0) && !(Integer.parseInt(_c.getText())== 0)) {
}
}
}
}
Introduction
Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section. Pay particular attention to the Performing Custom Painting section.
I reworked your GUI. Here's what it looks like now.
I move the X and Y axis around so that the graph fits in the drawing area. The minimum and maximum V values are no less than -10 and 10, respectively. I show the calculated Y minimum and maximum values in the entry panel. The X axis and Y axis are not to the same scale.
Explanation
When I create a Swing GUI, I use the model-view-controller (MVC) pattern. This pattern helps me to separate my concerns and focus on one small part of the application at a time.
The application model for a Swing GUI consists of one or more plain Java getter/setter classes.
The view consists of one and only one JFrame and as many JPanels as I need to create the GUI. You can nest multiple simple JPanels to create a complex layout.
The controller consists of one or more Actions or Listeners. There's usually not one controller to "rule them all". Each Action or Listener is responsible for its part of the model and view.
I didn't write all the code at once. I wrote a little and tested a lot. I probably ran 150 - 200 tests of the GUI before I was satisfied.
Model
I created one plain Java getter/setter class, the GraphPlotterModel class. This class holds the X and Y minimum and maximum values, and a java.util.List of Point2D instances that make up the graph. I also define a starting Dimension in pixels for the drawing JPanel. The dimensions of the drawing JPanel can change. One way is to maximize the GUI.
The model also holds the calculation of the quadratic equation. I go from the X minimum to the X maximum, calculating the corresponding Y value. The X and Y values are in units.
View
I started the GUI with a call to the SwingUtilities invokeLater method. This method ensures that the Swing components are created and executed on the Event Dispatch Thread.
I separated the creation of the JFrame from the creation of the JPanels. This allows me to separate my concerns and focus on one small part of the application at a time. The top JPanel is made up of two individual JPanels, one for the title and one for the entry fields. The center JPanel is a standard drawing panel.
Generally, you define Swing components on a JPanel in column, row order. This makes the code easier to read and understand.
The drawing panel has a method to convert units to pixels. This method probably took 1/3 of my total development time. The biggest hurdle is that a standard graph goes up from the Y minimum to the Y maximum and the Y pixels go from top to bottom. I basically use ratios to calculate the pixels.
Controller
There's only one JButton, so there's only one ActionListener. I made it a separate private class because it has a lot of code and I didn't want to have to pass 5 input fields to a separate class. I check to make sure all the inputs are valid double values, but I didn't display any error message.
Code
Here's the complete runnable code. I made all the additional public classes inner classes so I could post the code as one block.
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Point2D;
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.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class GraphPlotter implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new GraphPlotter());
}
private final GraphPlotterModel model;
private final DrawingPanel drawingPanel;
private JTextField aField, bField, cField;
private JTextField xMinField, xMaxField, yMinField, yMaxField;
public GraphPlotter() {
this.model = new GraphPlotterModel();
this.drawingPanel = new DrawingPanel(model);
}
#Override
public void run() {
JFrame frame = new JFrame("Graph Plotter");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createEntryPanel(), BorderLayout.NORTH);
frame.add(drawingPanel, BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createEntryPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
Font font = panel.getFont().deriveFont(16f);
Font titleFont = panel.getFont().deriveFont(Font.BOLD, 24f);
JPanel titlePanel = new JPanel(new FlowLayout());
titlePanel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
JLabel label = new JLabel(
"Plot the quadratic equation f(x) = ax² + bx + c");
label.setFont(titleFont);
titlePanel.add(label);
JPanel entryPanel = new JPanel(new FlowLayout());
entryPanel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));
label = new JLabel("f(x) =");
label.setFont(font);
entryPanel.add(label);
aField = new JTextField(5);
aField.setFont(font);
entryPanel.add(aField);
label = new JLabel("x² +");
label.setFont(font);
entryPanel.add(label);
bField = new JTextField(5);
bField.setFont(font);
entryPanel.add(bField);
label = new JLabel("x +");
label.setFont(font);
entryPanel.add(label);
cField = new JTextField(5);
cField.setFont(font);
entryPanel.add(cField);
entryPanel.add(Box.createHorizontalStrut(30));
label = new JLabel("X min:");
label.setFont(font);
entryPanel.add(label);
xMinField = new JTextField(5);
xMinField.setFont(font);
entryPanel.add(xMinField);
label = new JLabel("X max:");
label.setFont(font);
entryPanel.add(label);
xMaxField = new JTextField(5);
xMaxField.setFont(font);
entryPanel.add(xMaxField);
label = new JLabel("Y min:");
label.setFont(font);
entryPanel.add(label);
yMinField = new JTextField(5);
yMinField.setEditable(false);
yMinField.setFont(font);
entryPanel.add(yMinField);
label = new JLabel("Y max:");
label.setFont(font);
entryPanel.add(label);
yMaxField = new JTextField(5);
yMaxField.setEditable(false);
yMaxField.setFont(font);
entryPanel.add(yMaxField);
entryPanel.add(Box.createHorizontalStrut(30));
JButton button = new JButton("Plot");
button.addActionListener(new PlotListener());
button.setFont(font);
entryPanel.add(button);
updateEntryPanel();
panel.add(titlePanel, BorderLayout.NORTH);
panel.add(entryPanel, BorderLayout.SOUTH);
return panel;
}
public void updateEntryPanel() {
String formatter = "%.2f";
aField.setText(String.format(formatter, model.getA()));
bField.setText(String.format(formatter, model.getB()));
cField.setText(String.format(formatter, model.getC()));
xMinField.setText(String.format(formatter, model.getxMin()));
xMaxField.setText(String.format(formatter, model.getxMax()));
yMinField.setText(String.format(formatter, model.getyMin()));
yMaxField.setText(String.format(formatter, model.getyMax()));
}
public void repaint() {
drawingPanel.repaint();
}
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = 1L;
private final int margin;
private final GraphPlotterModel model;
public DrawingPanel(GraphPlotterModel model) {
this.model = model;
this.margin = 20;
this.setPreferredSize(model.getDrawingAreaDimension());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setColor(Color.BLACK);
g2d.setStroke(new BasicStroke(3f));
int width = getWidth() - margin - margin;
int height = getHeight() - margin - margin;
double xMin = model.getxMin();
double xMax = model.getxMax();
double yMin = model.getyMin();
double yMax = model.getyMax();
// Draw X Axis
Point2D a = new Point2D.Double(xMin, 0.0);
Point2D b = new Point2D.Double(xMax, 0.0);
Point startPoint = toPixels(a, width, height);
Point endPoint = toPixels(b, width, height);
g2d.drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y);
// Draw Y axis
a = new Point2D.Double(0.0, yMin);
b = new Point2D.Double(0.0, yMax);
startPoint = toPixels(a, width, height);
endPoint = toPixels(b, width, height);
g2d.drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y);
// Draw graph
g2d.setColor(Color.BLUE);
Point previousPoint = null;
List<Point2D> points = model.getPoints();
for (Point2D point : points) {
Point drawPoint = toPixels(point, width, height);
// System.out.println(point + " " + drawPoint);
if (previousPoint != null) {
g2d.drawLine(previousPoint.x, previousPoint.y, drawPoint.x,
drawPoint.y);
}
previousPoint = (Point) drawPoint.clone();
}
}
private Point toPixels(Point2D point, int width, int height) {
double xMin = model.getxMin();
double xMax = model.getxMax();
double yMin = model.getyMin();
double yMax = model.getyMax();
// System.out.println(yMin + " " + yMax);
double xDelta = (xMax - xMin) / width;
double yDelta = (yMax - yMin) / height;
double xx = Math.round((point.getX() - xMin) / xDelta);
double yy = Math.round((point.getY() - yMin) / yDelta);
// X in pixels goes from left to right
int x = (int) xx + margin;
// Y in pixels goes from top to bottom
int y = height - (int) yy + margin;
return new Point(x, y);
}
}
private class PlotListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent event) {
String aString = aField.getText().trim();
String bString = bField.getText().trim();
String cString = cField.getText().trim();
String xMinString = xMinField.getText().trim();
String xMaxString = xMaxField.getText().trim();
double a = valueOf(aString);
if (a == Double.MIN_VALUE) {
return;
}
double b = valueOf(bString);
if (b == Double.MIN_VALUE) {
return;
}
double c = valueOf(cString);
if (c == Double.MIN_VALUE) {
return;
}
double xMin = valueOf(xMinString);
if (xMin == Double.MIN_VALUE) {
return;
}
double xMax = valueOf(xMaxString);
if (xMax == Double.MIN_VALUE) {
return;
}
model.setA(a);
model.setB(b);
model.setC(c);
model.setxMin(xMin);
model.setxMax(xMax);
model.calculatePlot();
updateEntryPanel();
repaint();
}
private double valueOf(String s) {
try {
return Double.valueOf(s);
} catch (NumberFormatException e) {
return Double.MIN_VALUE;
}
}
}
public class GraphPlotterModel {
/** f(x) = ax² + bx + c */
private double a, b, c, xMin, xMax, yMin, yMax;
private final List<Point2D> points;
private final Dimension drawingAreaDimension;
public GraphPlotterModel() {
this.drawingAreaDimension = new Dimension(500, 500);
this.points = new ArrayList<>();
this.xMin = -10.0;
this.xMax = 10.0;
this.yMin = -10.0;
this.yMax = 10.0;
}
public void calculatePlot() {
// steps should be an even number
int steps = 100;
double xDelta = (xMax - xMin) / steps;
double x = xMin;
double yMin = Double.MAX_VALUE;
double yMax = Double.MIN_VALUE;
points.clear();
for (int index = 0; index <= steps; index++) {
double y = a * x * x + b * x + c;
Point2D point = new Point2D.Double(x, y);
points.add(point);
x += xDelta;
yMax = Math.max(yMax, y);
yMin = Math.min(yMin, y);
}
// Make sure that Y goes from -10 to 10 at a minimum
this.yMax = Math.max(yMax, 10.0);
this.yMin = Math.min(yMin, -10.0);
}
public Dimension getDrawingAreaDimension() {
return drawingAreaDimension;
}
public double getA() {
return a;
}
public void setA(double a) {
this.a = a;
}
public double getB() {
return b;
}
public void setB(double b) {
this.b = b;
}
public double getC() {
return c;
}
public void setC(double c) {
this.c = c;
}
public double getxMin() {
return xMin;
}
public void setxMin(double xMin) {
this.xMin = xMin;
}
public double getxMax() {
return xMax;
}
public void setxMax(double xMax) {
this.xMax = xMax;
}
public List<Point2D> getPoints() {
return points;
}
public double getyMin() {
return yMin;
}
public double getyMax() {
return yMax;
}
}
}
So I have this canvas, a BufferedImage, and I have two default calls where I make a line and a circle. My issue here is that I'm trying to call, lets say drawCircle(...) in when a user lets say put 1 into the textfield and sumbit it with enter like this:
if (input.equals("1")){
System.out.println("drawCircle");
DrawCanvas drawCanvas = new DrawCanvas();
drawCanvas.drawCircle(330,310,50);
}
But when I write 1 in the textfield and submit that, I only get the system output "drawCircle", but the circle is not shown?
I thought that my reprint() would update it, but it doesn't, so I'm a bit stuck..
Here is the code I use for making the circle and line and so on:
package DrawCanvas;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
public class DrawCanvas extends JPanel {
final private BufferedImage canvas;
final private Color def_c = Color.BLACK; final private Color def_bg = Color.LIGHT_GRAY;
public DrawCanvas() {
int width = 1280; int height = 720;
canvas = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
fillCanvas(def_bg);
int x0 = 0;
int x1 = 100;
int y0 = 0;
int y1 = 100;
//drawRect(Color.RED, 0, 0, width/2, height/2);
drawLine(def_c, x0, y0, x1, y1);
//drawLineRecInit(Color.yellow, x0, y0+2, x1, y1+2);
drawCircle(300,300,100);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(canvas.getWidth(), canvas.getHeight());
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.drawImage(canvas, null, null);
}
public void fillCanvas(Color c) {
int color = c.getRGB();
for (int x = 0; x < canvas.getWidth(); x++) {
for (int y = 0; y < canvas.getHeight(); y++) {
canvas.setRGB(x, y, color);
}
}
repaint();
}
// Implementation from Wikipedia: https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm#All_cases
public void drawLine(Color c, int x0, int y0, int x1, int y1)
{
int dx = Math.abs(x1-x0);
int sx = x0 < x1 ? 1 : -1;
int dy = -Math.abs(y1-y0);
int sy = y0 < y1 ? 1 : -1;
int err = dx + dy; /* error value e_xy */
while (true) /* loop */
{
canvas.setRGB(x0, y0, c.getRGB());
if (x0 == x1 && y0 == y1) break;
int e2 = 2*err;
if (e2 >= dy) /* e_xy+e_x > 0 */
{
err += dy;
x0 += sx;
}
if (e2 <= dx) /* e_xy+e_y < 0 */
{
err += dx;
y0 += sy;
}
}
repaint();
}
public void drawCircle(int x_center, int y_center, int r){
// inspiration : https://www.gatevidyalay.com/mid-point-circle-drawing-algorithm/
Color c = def_c;
int x=r, y=0, p = 1-r;
// checking for radius of circle
if(r==0){
drawPoint(x_center,y_center,c);
}
if(r<0)
return;
// initialising point p
while(x>y){
y++;
if (p < 0) {
p = p + 2 * y + 1;
} else {
x--;
p = p+2*y-2*x+1;
}
//print all octaves
drawPoint(x + x_center,y + y_center,c); // 1. (x,y)
drawPoint(y + x_center,x + y_center,c); // 1. (y,x)
drawPoint(y + x_center,-x + y_center,c); // 4. (y,-x)
drawPoint(x + x_center,-y + y_center,c); // 4. (x,-y)
drawPoint(-x + x_center,-y + y_center,c); // 3. (-x,-y)
drawPoint(-y + x_center,-x + y_center,c); // 3. (-y,-x)
drawPoint(-y + x_center,x + y_center,c); // 2. (-y,x)
drawPoint(-x + x_center,y + y_center,c); // 2. (-x,y)
}
//show
repaint();
}
void drawPoint(int x,int y,Color c){
canvas.setRGB(x,y, c.getRGB());
}
}
My User interface
import DrawCanvas.DrawCanvas;
import TextDemo.TextDemo;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Locale;
public class GUI extends JPanel{
public static void main(String[] args){
//Schedule a job for the event dispatch thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
int width = 1280; int height = 720;
//Create and set up the window.
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(width, height);
frame.setLayout(new BorderLayout(3,3));
JPanel panel1 = new JPanel();
JPanel panel2 = new JPanel();
JPanel panel3 = new JPanel();
panel1.setBackground(Color.red);
panel2.setBackground(Color.green);
panel3.setBackground(Color.yellow);
panel1.setPreferredSize(new Dimension(200, 100));
panel2.setSize(new Dimension(500, 500));
panel3.setPreferredSize(new Dimension(100, 100));
//Add contents to the window.
//frame.add(panel1,BorderLayout.WEST);
frame.add(new TextDemo(),BorderLayout.WEST);
frame.add(new DrawCanvas(),BorderLayout.CENTER);
frame.add(panel3,BorderLayout.SOUTH);
//Display the window.
frame.pack();
frame.setVisible(true);
}
}
This is where the user can ener a text
package TextDemo;
import DrawCanvas.DrawCanvas;
import java.awt.*;
import java.awt.event.*;
import java.util.Locale;
import javax.swing.*;
public class TextDemo extends JPanel implements ActionListener {
protected JTextField textField;
protected JTextArea textArea;
private final static String newline = "\n";
public static Boolean circle = false;
public TextDemo() {
super(new GridBagLayout());
textField = new JTextField(20);
textField.addActionListener(this);
textArea = new JTextArea(5, 20);
textArea.setEditable(false);
JScrollPane scrollPane = new JScrollPane(textArea);
//Add Components to this panel.
GridBagConstraints c = new GridBagConstraints();
c.gridwidth = GridBagConstraints.REMAINDER;
c.fill = GridBagConstraints.BOTH;
c.weightx = 1.0;
c.weighty = 1.0;
add(scrollPane, c);
c.weightx = 0;
c.weighty = 0;
c.fill = GridBagConstraints.HORIZONTAL;
add(textField, c);
}
public void actionPerformed(ActionEvent evt) {
String text = textField.getText();
textArea.append(text + newline);
//Make sure the new text is visible, even if there
//was a selection in the text area.
textArea.setCaretPosition(textArea.getDocument().getLength());
System.out.println("String is: " + textField.getText().toLowerCase(Locale.ROOT).replaceAll("\\s+",""));
String input = textField.getText().toLowerCase(Locale.ROOT).replaceAll("\\s+","");
if (input.equals("1")){
System.out.println("Here");
DrawCanvas drawCanvas = new DrawCanvas();
drawCanvas.drawCircle(330,310,50);
}
textField.setText("");
}
}
This is my first trial in java Swing. The issue am having is recreating the calendar panel every time the month changes. I would like to have the panelRightDown repopulated when addMonth is called (when > or < is clicked). I have tried calling revalidate, invalidate, repaint in addMonth but everything just goes haywire. The same methods ought to be implemented while calculating the year. Any help would be appreciated. More so, a better approach to this is highly welcome.
public class Gui extends JFrame {
private final int windowWidth = 700;
private final int windowHeight = 600;
private final Container container;
private final JPanel panelLeft = new JPanel();
private final JPanel panelRight = new JPanel();
private final GridBagConstraints gridBagConstraints = new GridBagConstraints();
private final int verticalSpacerSize = 8;
private final int horizontalSpacerSize = 15;
private Border lowerEtchedBorder =
BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);
// -----
protected boolean controlsOnTop;
protected boolean removeOnDaySelection;
protected Calendar currentDisplayDate;
protected JButton prevMonth;
protected JButton nextMonth;
protected JButton prevYear;
protected JButton nextYear;
protected JTextField textField;
protected List<ActionListener> popupListeners =
new ArrayList<ActionListener>();
protected Popup popup;
protected SimpleDateFormat dayName = new SimpleDateFormat("d");
protected SimpleDateFormat monthName = new SimpleDateFormat("MMMM");
protected String iconFile = "datepicker.gif";
protected String[] weekdayNames =
{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
JPanel datePanel = new JPanel();
JPanel panelRightDown = new JPanel();
JPanel controlsPanel;
// -----
// Constructor to setup the GUI components and event handlers
public Gui() {
//-----
currentDisplayDate = Calendar.getInstance();
controlsOnTop = true;
removeOnDaySelection = true;
//createPanel();
// Retrieve the content-pane of the top-level container JFrame
// All operations done on the content-pane
container = getContentPane();
container.setLayout(new BorderLayout());
//container.setMinimumSize(new Dimension(windowWidth, windowHeight));
createMenuBar();
createStatusBar();
JPanel fullPane = new JPanel();
fullPane.setLayout(new GridBagLayout());
// Spacer
container.add(Box.createVerticalStrut(
4), BorderLayout.NORTH);
container.add(fullPane, BorderLayout.CENTER);
fullPane.setMinimumSize(new Dimension(windowWidth, windowHeight));
// Position Left and Right panels
gridBagConstraints.fill = GridBagConstraints.BOTH;
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.weightx = 0.3;
gridBagConstraints.weighty = 1.0;
fullPane.add(panelLeft, gridBagConstraints);
gridBagConstraints.gridx = 1;
gridBagConstraints.weightx = 0;
fullPane.add(Box.createHorizontalStrut(
15), gridBagConstraints);
gridBagConstraints.fill = GridBagConstraints.BOTH;
gridBagConstraints.gridx = 2;
gridBagConstraints.weightx = 0.9;
fullPane.add(panelRight, gridBagConstraints);
configurePanelLeft(panelLeft);
configurePanelRight(panelRight);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("Prod - Reminder");
setSize(windowWidth, windowHeight);
setLocationRelativeTo(null);
setVisible(true);
addWindowListener(new Terminator());
}
public void setDate(String date) {
currentDisplayDate = Calendar.getInstance();
editDate(date);
}
public void setDate(Calendar date) {
currentDisplayDate = date;
//createPanel();
validate();
repaint();
}
public void setDate(int month, int day, int year) {
currentDisplayDate = Calendar.getInstance();
currentDisplayDate.set(expandYear(year), month - 1, day);
//createPanel();
validate();
repaint();
}
protected int expandYear(int year) {
if (year < 100) { // 2 digit year
int currentYear = Calendar.getInstance().get(Calendar.YEAR);
int current2DigitYear = currentYear % 100;
int currentCentury = currentYear / 100 * 100;
// set 2 digit year range +20 / -80 from current year
int high2DigitYear = (current2DigitYear + 20) % 100;
if (year <= high2DigitYear) {
year += currentCentury;
}
else {
year += (currentCentury - 100);
}
}
return year;
}
public void setControlsOnTop(boolean flag) {
controlsOnTop = flag;
//createPanel();
repaint();
}
public Calendar getCalendarDate() {
return currentDisplayDate;
}
public Date getDate() {
return currentDisplayDate.getTime();
}
public String getFormattedDate() {
return Integer.toString(getMonth()) + "/" +
Integer.toString(getDay()) + "/" +
Integer.toString(getYear());
}
public int getMonth() {
return currentDisplayDate.get(Calendar.MONTH) + 1;
}
public int getDay() {
return currentDisplayDate.get(Calendar.DAY_OF_MONTH);
}
public int getYear() {
return currentDisplayDate.get(Calendar.YEAR);
}
protected JPanel createControls() {
JPanel c = new JPanel();
c.setBorder(BorderFactory.createRaisedBevelBorder());
c.setFocusable(true);
c.setLayout(new FlowLayout(FlowLayout.CENTER));
prevYear = new JButton("<<");
c.add(prevYear);
prevYear.setMargin(new Insets(0,0,0,0));
prevYear.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
addYear(-1);
}
});
prevMonth = new JButton("<");
c.add(prevMonth);
prevMonth.setMargin(new Insets(0,0,0,0));
prevMonth.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
addMonth(-1);
}
});
textField = new JTextField(getFormattedDate(), 10);
c.add(textField);
textField.setEditable(true);
textField.setEnabled(true);
textField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
editDate(textField.getText());
}
});
nextMonth = new JButton(">");
c.add(nextMonth);
nextMonth.setMargin(new Insets(0,0,0,0));
nextMonth.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
addMonth(+1);
}
});
nextYear = new JButton(">>");
c.add(nextYear);
nextYear.setMargin(new Insets(0,0,0,0));
nextYear.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
addYear(+1);
}
});
return c;
}
protected JPanel configureDatePicker() {
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
datePanel.setFocusable(true);
datePanel.setLayout(gridbag);
String month = monthName.format(currentDisplayDate.getTime());
String year = Integer.toString(getYear());
c.gridx = 0;
c.gridy = 0;
c.gridwidth = 7;
c.gridheight = 1;
JLabel title = new JLabel(month + " " + year);
datePanel.add(title, c);
Font font = title.getFont();
// Font titleFont = new Font(font.getName(), font.getStyle(),
// font.getSize() + 2);
Font weekFont = new Font(font.getName(), font.getStyle(),
font.getSize() - 2);
title.setFont(font);
c.gridy = 1;
c.weightx = 0.1;
c.weighty = 0.1;
c.gridwidth = 1;
c.gridheight = 1;
c.fill = GridBagConstraints.BOTH;
for (c.gridx = 0; c.gridx < 7; c.gridx++) {
JLabel label = new JLabel(
weekdayNames[c.gridx], SwingConstants.CENTER);
datePanel.add(label, c);
label.setFont(weekFont);
}
Calendar draw = (Calendar) currentDisplayDate.clone();
draw.set(Calendar.DATE, 1);
draw.add(Calendar.DATE, -draw.get(Calendar.DAY_OF_WEEK) + 1);
int monthInt = currentDisplayDate.get(Calendar.MONTH);
// monthInt = 0;
// System.out.println("Current month: " + monthInt);
c.gridwidth = 1;
c.gridheight = 1;
int width = getFontMetrics(weekFont).stringWidth(" Wed ");
int width1 = getFontMetrics(weekFont).stringWidth("Wed");
int height = getFontMetrics(weekFont).getHeight() +
(width - width1);
for (c.gridy = 2; c.gridy < 8; c.gridy++) {
for (c.gridx = 0; c.gridx < 7; c.gridx++) {
JButton dayButton;
// System.out.print("Draw month: " + draw.get(Calendar.MONTH));
if (draw.get(Calendar.MONTH) == monthInt) {
String dayString = dayName.format(draw.getTime());
if (draw.get(Calendar.DAY_OF_MONTH) < 10) {
dayString = " " + dayString;
}
dayButton = new JButton(dayString);
} else {
dayButton = new JButton();
dayButton.setEnabled(false);
}
// System.out.println(", day: " + dayName.format(draw.getTime()));
datePanel.add(dayButton, c);
Color color = dayButton.getBackground();
if ((draw.get(Calendar.DAY_OF_MONTH) == getDay()) &&
(draw.get(Calendar.MONTH) == monthInt)) {
dayButton.setBackground(Color.yellow);
// dayButton.setFocusPainted(true);
// dayButton.setSelected(true);
} else
dayButton.setBackground(color);
dayButton.setFont(weekFont);
dayButton.setFocusable(true);
//dayButton.setPreferredSize(new Dimension(width, height));
//dayButton.setMargin(new Insets(0,0,0,0));
dayButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
changeDay(e.getActionCommand());
}
});
//if (dateChange != null)
// dayButton.addActionListener(dateChange);
draw.add(Calendar.DATE, +1);
}
// if (draw.get(Calendar.MONTH) != monthInt) break;
}
return datePanel;
}
public void addMonth(int month) {
currentDisplayDate.add(Calendar.MONTH, month);
datePanel.invalidate();
controlsPanel.invalidate();
panelRightDown.validate();
datePanel = configureDatePicker();
controlsPanel = createControls();
panelRightDown.removeAll();
panelRightDown.add(controlsPanel);
panelRightDown.add(datePanel);
validate();
repaint();
}
public void addYear(int year) {
currentDisplayDate.add(Calendar.YEAR, year);
validate();
repaint();
}
public void editDate(String date) {
parseDate(date);
//createPanel();
validate();
repaint();
}
protected void parseDate(String date) {
String[] parts = date.split("/");
switch (parts.length) {
case 3:
currentDisplayDate.set(Calendar.MONTH,
Integer.valueOf(parts[0]) - 1);
currentDisplayDate.set(Calendar.DAY_OF_MONTH,
Integer.valueOf(parts[1]));
currentDisplayDate.set(Calendar.YEAR,
expandYear(Integer.valueOf(parts[2])));
break;
case 2:
currentDisplayDate = Calendar.getInstance();
currentDisplayDate.set(Calendar.MONTH,
Integer.valueOf(parts[0]) - 1);
currentDisplayDate.set(Calendar.DAY_OF_MONTH,
Integer.valueOf(parts[1]));
break;
default:
// invalid date
currentDisplayDate = Calendar.getInstance();
break;
}
}
public void changeDay(String day) {
currentDisplayDate.set(Calendar.DAY_OF_MONTH,
Integer.valueOf(day.trim()));
textField.setText(getFormattedDate());
if (!removeOnDaySelection) {
//createPanel();
//validate();
repaint();
}
}
private void createMenuBar() {
JMenuBar menubar = new JMenuBar();
JMenu file = new JMenu("File");
file.setMnemonic(KeyEvent.VK_F);
JMenuItem eMenuItem = new JMenuItem("Exit");
eMenuItem.setMnemonic(KeyEvent.VK_E);
eMenuItem.setToolTipText("Exit application");
eMenuItem.addActionListener((ActionEvent event) -> {
System.exit(0);
});
file.add(eMenuItem);
menubar.add(file);
setJMenuBar(menubar);
}
private void createStatusBar() {
// create the status bar panel and shove it down the bottom of the frame
JPanel statusPanel = new JPanel();
statusPanel.setBorder(new BevelBorder(BevelBorder.LOWERED));
container.add(statusPanel, BorderLayout.SOUTH);
statusPanel.setPreferredSize(new Dimension(container.getWidth(), 20));
statusPanel.setLayout(new BoxLayout(statusPanel, BoxLayout.X_AXIS));
JLabel statusLabel = new JLabel("status");
statusLabel.setHorizontalAlignment(SwingConstants.LEFT);
statusPanel.add(statusLabel);
}
public void configurePanelLeft(JPanel panel) {
// Configure Left-side panels
// Top panel
gridBagConstraints.fill = GridBagConstraints.BOTH;
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.weightx = 0.3;
gridBagConstraints.weighty = 0.3;
JPanel panelLeftTop = new JPanel();
panelLeftTop.setBorder(
BorderFactory.createMatteBorder(1, 1, 1, 1, Color.YELLOW));
panel.setLayout(new GridBagLayout());
panel.add(panelLeftTop, gridBagConstraints);
// Display Area
JTextArea displayItem = new JTextArea("Hello, left top!");
displayItem.setBorder(lowerEtchedBorder);
displayItem.setLineWrap(true);
displayItem.setBackground(panel.getBackground());
displayItem.setWrapStyleWord(true);
//displayItem.setEditable(false);
panelLeftTop.setLayout(new BorderLayout());
JScrollPane topScrollPane = new JScrollPane();
topScrollPane.getVerticalScrollBar().setUnitIncrement(3);
topScrollPane.setViewportView(displayItem);
topScrollPane.setHorizontalScrollBarPolicy(
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
panelLeftTop.add(topScrollPane);
// Spacer
gridBagConstraints.fill = GridBagConstraints.BOTH;
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 0;
panel.add(Box.createVerticalStrut(
verticalSpacerSize), gridBagConstraints);
// Bottom panel
gridBagConstraints.fill = GridBagConstraints.BOTH;
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 2;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 0.7;
JPanel panelLeftDown = new JPanel();
panelLeftDown.setBorder(
BorderFactory.createMatteBorder(1, 1, 1, 1, Color.BLUE));
panelLeftDown.setLayout(new GridBagLayout());
for (int i = 0; i < 50; i++) {
gridBagConstraints.fill = GridBagConstraints.BOTH;
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = i;
gridBagConstraints.weightx = 0.3;
//gridBagConstraints.weighty = 1.0;
String textValue = "Area: "+ i
+" This is a very long wrapped text, "
+ "which I expect to be an example of text in a label. "
+ "I really hope it works well."
+ "The Scroll Bar comes when your text goes beyond "
+ "the bounds of your view area. "
+ "Don't use Absolute Positioning, for such a small "
+ "talk at hand, always prefer Layout Managers, "
+ "do read the first para of the first link, "
+ "to know the advantage of using a Layout Manager.";
JTextArea textArea = new JTextArea(textValue);
textArea.setBorder(lowerEtchedBorder);
textArea.setLineWrap(true);
textArea.setBackground(panel.getBackground());
textArea.setWrapStyleWord(true);
textArea.setEditable(false);
textArea.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {
displayItem.setText(textValue);
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
topScrollPane.getVerticalScrollBar().setValue(0);
}
});
}
#Override
public void mousePressed(MouseEvent e) {
//throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
#Override
public void mouseReleased(MouseEvent e) {
//throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
#Override
public void mouseEntered(MouseEvent e) {
//throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
#Override
public void mouseExited(MouseEvent e) {
//throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
});
panelLeftDown.add(textArea, gridBagConstraints);
}
JScrollPane scrollPane = new JScrollPane(panelLeftDown,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
panelLeftDown.setAutoscrolls(true);
scrollPane.setPreferredSize(new Dimension(300,800));
scrollPane.getVerticalScrollBar().setUnitIncrement(3);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
scrollPane.getVerticalScrollBar().setValue(0);
}
});
panel.add(scrollPane, gridBagConstraints);
}
public void configurePanelRight(JPanel panel) {
// Configure right-side panels
// Top panel
gridBagConstraints.fill = GridBagConstraints.BOTH;
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 0.1;
JPanel panelRightTop = new JPanel();
panelRightTop.setBorder(
BorderFactory.createMatteBorder(1, 1, 1, 1, Color.YELLOW));
panelRightTop.add(new JLabel("Hello, right top!"));
panel.setLayout(new GridBagLayout());
panel.add(panelRightTop, gridBagConstraints);
// Spacer
gridBagConstraints.fill = GridBagConstraints.BOTH;
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 0;
panel.add(Box.createVerticalStrut(
verticalSpacerSize), gridBagConstraints);
// Bottom panel
gridBagConstraints.fill = GridBagConstraints.BOTH;
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 2;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 0.9;
panelRightDown.setBorder(
BorderFactory.createMatteBorder(1, 1, 1, 1, Color.BLUE));
//panelRightDown.add(new JLabel("Hello, right down!"));
panel.add(panelRightDown, gridBagConstraints);
panel.add(panelRightDown, gridBagConstraints);
// Date Picker
gridBagConstraints.fill = GridBagConstraints.BOTH;
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 0.1;
panelRightDown.setLayout(new BorderLayout());
datePanel = configureDatePicker();
controlsPanel = createControls();
panelRightDown.add(controlsPanel, BorderLayout.NORTH);
panelRightDown.add(datePanel, BorderLayout.CENTER);
}
private ListCellRenderer<? super String> getRenderer() {
return new DefaultListCellRenderer(){
#Override
public Component getListCellRendererComponent(JList<?> list,
Object value, int index, boolean isSelected,
boolean cellHasFocus) {
JLabel listCellRendererComponent =
(JLabel) super.getListCellRendererComponent(
list, value, index, isSelected,cellHasFocus);
listCellRendererComponent.setBorder(
lowerEtchedBorder);
listCellRendererComponent.setEnabled(true);
return listCellRendererComponent;
}
};
}
public static void main(String[] args) {
// Run the GUI construction in the Event-Dispatching thread for thread-safety
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Gui(); // Let the constructor do the job
}
});
}
}
The first image shows what the GUI looks like when I just start it, the second shows what happens when I click around the board. The chess pieces show up at the top row after I click a piece and then click on a button on the top row. What is happening here?!
The code is below; this class is where I have most of my code. The rest of the classes are just loading images at this point. The Board constructor is called in the main to build the GUI.
public class BoardPanel extends JPanel {
public BoardPanel() {
createBoard();
}
private void createBoard(){
setLayout(new GridLayout(10, 10));
// Makes a 10 x 10 grid of black and white colors
for (int i = 0; i<10; i++){
for (int j = 0; j<10; j++){
square[i][j] = new JButton();
square[i][j].setRolloverEnabled(false);
if ((i+j)%2 == 0)
square[i][j].setBackground(Color.WHITE);
else
square[i][j].setBackground(Color.LIGHT_GRAY);
add(square[i][j]);
}
}
addLabels();
//Colors the corner squares
square[0][0].setBackground(new Color(155, 234, 242, 100));
square[0][9].setBackground(new Color(155, 234, 242, 100));
square[9][0].setBackground(new Color(155, 234, 242, 100));
square[9][9].setBackground(new Color(155, 234, 242, 100));
}
private void addLabels(){
//Adds labels to the ranks
for (int i =1 ; i< 9; i++){
square[i][0].setBackground(new Color(155, 234, 242, 100));
square[i][0].setText(rank[8-i]);
square[i][0].setHorizontalTextPosition(SwingConstants.RIGHT);
square[i][9].setBackground(new Color(155, 234, 242, 100));
square[i][9].setText(rank[8-i]);
square[i][9].setHorizontalTextPosition(SwingConstants.LEFT);
}
//Adds labels to the files
for (int j = 1; j<9;j++){
square[0][j].setBackground(new Color(155, 234, 242, 100));
square[0][j].setText(file[j-1]);
square[0][j].setVerticalTextPosition(SwingConstants.BOTTOM);
square[9][j].setBackground(new Color(155, 234, 242, 100));
square[9][j].setText(file[j-1]);
square[9][j].setVerticalTextPosition(SwingConstants.TOP);
}
JButton square[][] = new JButton[10][10];
String[] rank = {"1","2","3","4","5","6","7","8"};
String[] file = {"a","b","c","d","e","f","g","h"};
}
}
The main class
public class Board {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.add(new BoardPanel());
frame.setVisible(true);
frame.setSize(900, 700);
}
}
Your problem is with the button thinking that it is fully opaque when it is in fact not opaque. As per Kleopatra in this answer, you must make the button non-opaque and take over the painting mechanisms
square[i][j] = new JButton() {
#Override // !! add this:
protected void paintComponent(Graphics g) {
if (!isOpaque() && getBackground().getAlpha() < 255) {
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
}
super.paintComponent(g);
}
};
square[i][j].setRolloverEnabled(false);
square[i][j].setOpaque(false); // !! and also add this *******
As a side note, I wouldn't be using JButtons for this type of problem, but rather I'd be using JPanels, and would place my chess pieces as ImageIcons displayed in JLabels, labels that are added to or removed from the appropriate chess-board squares.
A board without buttons and without use of alpha colors:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.*;
#SuppressWarnings("serial")
public class Board2 extends JPanel {
private static final int SIDE_LEN = 80;
private static final Dimension SQUARE_SZ = new Dimension(SIDE_LEN, SIDE_LEN);
private static final Color EDGE_COLOR = new Color(165, 245, 250);
private static final Color DARK_SQR_COLOR = Color.LIGHT_GRAY;
private static final Color LIGHT_SQR_COLOR = Color.WHITE;
private JPanel[][] chessSquares = new JPanel[8][8];
public Board2() {
setLayout(new GridLayout(10, 10)); // sorry for magic numbers
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if ((i == 0 || i == 9) && (j == 0 || j == 9)) {
add(createEdgePanel(""));
} else if (i == 0 || i == 9) {
String text = String.valueOf((char) (j + 'a' - 1));
add(createEdgePanel(text));
} else if (j == 0 || j == 9) {
String text = String.valueOf(8 - i + 1);
add(createEdgePanel(text));
} else {
JPanel panel = createSquare(i, j);
add(panel);
}
}
}
}
private JPanel createSquare(int i, int j) {
JPanel panel = new JPanel(new GridBagLayout());
Color c = (i % 2 == j % 2) ? LIGHT_SQR_COLOR : DARK_SQR_COLOR;
panel.setBackground(c);
panel.setPreferredSize(SQUARE_SZ);
panel.setBorder(BorderFactory.createLineBorder(Color.GRAY));
return panel;
}
private JPanel createEdgePanel(String text) {
JLabel label = new JLabel(text, SwingConstants.CENTER);
JPanel panel = new JPanel(new GridBagLayout());
panel.add(label);
panel.setBackground(EDGE_COLOR);
panel.setPreferredSize(SQUARE_SZ);
panel.setBorder(BorderFactory.createLineBorder(Color.GRAY));
return panel;
}
private static void createAndShowGui() {
Board2 mainPanel = new Board2();
JFrame frame = new JFrame("Board2");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Which on my system looks like:
Now with some pieces added:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.*;
#SuppressWarnings("serial")
public class Board2 extends JPanel {
private static final int SIDE_LEN = 80;
private static final Dimension SQUARE_SZ = new Dimension(SIDE_LEN, SIDE_LEN);
private static final String SPRITE_PATH = "http://i.stack.imgur.com/memI0.png";
private static final int SPRITE_ROWS = 2;
private static final int SPRITE_COLS = 6;
private static final Color EDGE_COLOR = new Color(165, 245, 250);
private static final Color DARK_SQR_COLOR = Color.LIGHT_GRAY;
private static final Color LIGHT_SQR_COLOR = Color.WHITE;
private static final int ROWS = 8;
private JLabel[][] chessSquares = new JLabel[ROWS][ROWS];
private BufferedImage bigImage;
private List<Icon> icons = new ArrayList<>();
public Board2() throws IOException {
URL imgUrl = new URL(SPRITE_PATH);
bigImage = ImageIO.read(imgUrl);
int w = bigImage.getWidth() / SPRITE_COLS;
int h = bigImage.getHeight() / SPRITE_ROWS;
for (int i = 0; i < SPRITE_ROWS; i++) {
for (int j = 0; j < SPRITE_COLS; j++) {
int x = (j * bigImage.getWidth()) / SPRITE_COLS;
int y = (i * bigImage.getHeight()) / SPRITE_ROWS;
BufferedImage spriteImg = bigImage.getSubimage(x, y, w, h);
Icon spriteIcon = new ImageIcon(spriteImg);
icons.add(spriteIcon);
}
}
for (int i = 0; i < chessSquares.length; i++) {
for (int j = 0; j < chessSquares[i].length; j++) {
chessSquares[i][j] = new JLabel();
}
}
setLayout(new GridLayout(ROWS + 2, ROWS + 2)); // sorry for magic numbers
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if ((i == 0 || i == ROWS + 1) && (j == 0 || j == ROWS + 1)) {
add(createEdgePanel(""));
} else if (i == 0 || i == ROWS + 1) {
String text = String.valueOf((char) (j + 'a' - 1));
add(createEdgePanel(text));
} else if (j == 0 || j == ROWS + 1) {
String text = String.valueOf(ROWS - i + 1);
add(createEdgePanel(text));
} else {
JPanel panel = createSquare(i, j);
panel.add(chessSquares[i - 1][j - 1]);
add(panel);
}
}
}
setPieces(0, 0, 2); // rooks
setPieces(1, 0, 3); // knights
setPieces(2, 0, 4); // bishops
// kings and queens
chessSquares[0][3].setIcon(icons.get(1));
chessSquares[7][3].setIcon(icons.get(6 + 1));
chessSquares[0][4].setIcon(icons.get(0));
chessSquares[7][4].setIcon(icons.get(6 + 0));
// pawns
for (int i = 0; i < ROWS / 2; i++) {
setPieces(i, 1, 5);
}
}
private void setPieces(int colPos, int rowPos, int pieceIndex) {
chessSquares[rowPos][colPos].setIcon(icons.get(pieceIndex));
chessSquares[rowPos][ROWS - 1 - colPos].setIcon(icons.get(pieceIndex));
chessSquares[ROWS - 1 - rowPos][colPos].setIcon(icons.get(6 + pieceIndex));
chessSquares[ROWS - 1 - rowPos][ROWS - 1 - colPos].setIcon(icons
.get(6 + pieceIndex));
}
private void setPiece(int colPos, int pieceIndex) {
chessSquares[0][colPos].setIcon(icons.get(pieceIndex));
chessSquares[ROWS - 1][ROWS - 1 - colPos].setIcon(icons.get(6 + pieceIndex));
}
private JPanel createSquare(int i, int j) {
JPanel panel = new JPanel(new GridBagLayout());
Color c = (i % 2 == j % 2) ? LIGHT_SQR_COLOR : DARK_SQR_COLOR;
panel.setBackground(c);
panel.setPreferredSize(SQUARE_SZ);
panel.setBorder(BorderFactory.createLineBorder(Color.GRAY));
return panel;
}
private JPanel createEdgePanel(String text) {
JLabel label = new JLabel(text, SwingConstants.CENTER);
JPanel panel = new JPanel(new GridBagLayout());
panel.add(label);
panel.setBackground(EDGE_COLOR);
panel.setPreferredSize(SQUARE_SZ);
panel.setBorder(BorderFactory.createLineBorder(Color.GRAY));
return panel;
}
private static void createAndShowGui() {
Board2 mainPanel = null;
try {
mainPanel = new Board2();
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
JFrame frame = new JFrame("Board2");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
This is my class:
public class Main extends JFrame{
private Container container;
private GridBagConstraints cons;
private JPanel panelDisplay;
private int curX = 0, curY = 0;
public Main() {
initComp();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Main ex = new Main();
ex.setVisible(true);
}
});
}
private void initComp()
{
container = this.getContentPane();
container.setLayout(new GridBagLayout());
cons = new GridBagConstraints();
cons.gridx = 0;
cons.gridy = 0;
container.add(new PanelNot(), cons);
panelDisplay = new JPanel();
panelDisplay.setBackground(Color.blue);
panelDisplay.setPreferredSize(new Dimension(600, 400));
panelDisplay.setLayout(new GridBagLayout());
cons.gridx = 1;
cons.gridy = 0;
container.add(panelDisplay, cons);
for (int i = 0; i < 15; i++) // display 15 components
{
displayNot();
}
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //setting the default close operation of JFrame
this.pack();
this.setResizable(false);
this.setLocationRelativeTo(null);
this.setVisible(true);
}
private void displayNot()
{
setLocGrid();
panelDisplay.add(new Not1(), cons);
}
private void setLocGrid()
{
if(curX==11) // maximum component to be display in 1 row is 11
{
curY += 1;
curX = 0;
}
cons.gridx = curX;
cons.gridy = curY;
cons.anchor = GridBagConstraints.FIRST_LINE_START;
cons.weightx = 1.0;
cons.weighty = 1.0;
curX += 1;
}
}
this is the output:
Just ignore the left panel. My problem is in the right panel which is, there is a gap between one component (component: Not1) to the other. i have set the preferedSize of each component to x=20 and y=30 as you can see in every component's background where the color is gray. So my question is, how to make the gap disappear?
UPDATE : my expectation:
Start by getting rid of cons.weightx and cons.weightx
private void setLocGrid() {
if (curX == 11) // maximum component to be display in 1 row is 11
{
curY += 1;
curX = 0;
}
cons.gridx = curX;
cons.gridy = curY;
cons.anchor = GridBagConstraints.FIRST_LINE_START;
//cons.weightx = 1.0;
//cons.weighty = 1.0;
curX += 1;
}
This will get you something like...
Now, you need some kind of filler that can push the components to the top/left position, for example...
for (int i = 0; i < 15; i++) // display 15 components
{
displayNot();
}
cons.gridy++;
cons.gridx = 12; // Based on you conditions in setLocGrid
cons.weightx = 1;
cons.weighty = 1;
JPanel filler = new JPanel();
filler.setOpaque(false);
panelDisplay.add(filler, cons);
Which will give you something like...