This one's a tough one - I have a JFrame that generates JTextFields. When I go from generating 2 JTextFields to 12 JTextfields (for example), I see some error where there is an extra differently-sized JTextField at the end. It seems to be a repaint error.
Main.java code:
import java.awt.*;
import javax.swing.*;
public class Main {
public static Display display = new Display();
public static void main(String[] args) {
display.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
display.setVisible(true);
}
}
Display.java code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Display extends JFrame {
final int FRAME_WIDTH = 820;
final int FRAME_HEIGHT = 700;
final int X_OFFSET = 40;
final int Y_OFFSET = 40;
final int GRAPH_OFFSETX = 35;
final int GRAPH_OFFSETY = 60;
final int GRAPH_WIDTH = 500;
final int GRAPH_HEIGHT = 500;
final int GRAPH_INTERVAL = 20;
JButton submit;
JTextField top;
JTextField bottom;
JTextField numPoint;
JPanel bpanel;
JPanel points;
int maxPoints;
public Display() {
init();
}
public void init() {
setBackground(Color.WHITE);
setLocation(X_OFFSET, Y_OFFSET);
setSize(FRAME_WIDTH, FRAME_HEIGHT);
setTitle("Geometric Transformations");
getContentPane().setLayout(null);
setDefaultLookAndFeelDecorated(true);
top = new JTextField(); // parameter is size of input characters
top.setText("1 2 3");
top.setBounds(590, 150, 120, 25);
bottom = new JTextField(); // parameter is size of input characters
bottom.setText("5 6 7");
bottom.setBounds(590, 200, 120, 25);
numPoint = new JTextField();
numPoint.setText("Number of Points?");
numPoint.setBounds(550,200,200,25);
this.add(numPoint);
SubmitButton submit = new SubmitButton("Submit");
submit.setBounds(570, 250, 170, 25);
bpanel = new JPanel(new GridLayout(2,3));
bpanel.add(top);
bpanel.add(bottom);
bpanel.add(submit);
points = new JPanel(new GridLayout(2,2));
points.setBounds(540,250,265,60);
this.add(points);
bpanel.setBounds(550,100,200,70);
this.add(bpanel, BorderLayout.LINE_START);
Component[] a = points.getComponents();
System.out.println(a.length);
repaint();
}
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.WHITE);
g.fillRect(100, 100, 20, 30);
g.setColor(Color.BLACK);
genGraph(g, GRAPH_OFFSETX, GRAPH_OFFSETY, GRAPH_WIDTH, GRAPH_HEIGHT, GRAPH_INTERVAL);
}
public void genGraph (Graphics g, int x, int y, int width, int height, int interval) {
// draw background
int border = 5;
g.setColor(Color.BLACK);
width = width - (width % interval);
height = height - (height % interval);
for (int col=x; col <= x+width; col+=interval) {
g.drawLine(col, y, col, y+height);
}
for (int row=y; row <= y+height; row+=interval) {
g.drawLine(x, row, x+width, row);
}
}
class SubmitButton extends JButton implements ActionListener {
public SubmitButton(String title){
super(title);
addActionListener(this);
this.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
maxPoints = Integer.parseInt(numPoint.getText()) * 2;
points.removeAll();
for (int i=0; i<maxPoints; i++) {
JTextField textField = new JTextField();
points.add(textField);
}
points.validate(); // necessary when adding components to a JPanel
// http://stackoverflow.com/questions/369823/java-gui-repaint-problem-solved
// What to Check:
// Things between commas are either spaces (which will be stripped later)
// or numbers!
// Pairs must match up!
}
}
}
The new components are redrawn over the previous ones.
I added points.repaint(); after points.validate(); and the problem was gone.
Note: I was annoyed with the issue of repainting of the grid too (put the window in front then back, you will see).
From a quick search, it seems better to avoid painting directly on the JFrame, but instead delegate that to a sub-component. If I am wrong, somebody tell me.
Here is my solution (imperfect, I leave to you the task to improve it... :-P
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SODisplay extends JFrame {
final int FRAME_WIDTH = 820;
final int FRAME_HEIGHT = 700;
final int X_OFFSET = 40;
final int Y_OFFSET = 40;
JButton submit;
JTextField top;
JTextField bottom;
JTextField numPoint;
JPanel bpanel;
JPanel points;
GridPanel grid;
int maxPoints;
public SODisplay() {
init();
}
public void init() {
setBackground(Color.WHITE);
setLocation(X_OFFSET, Y_OFFSET);
setSize(FRAME_WIDTH, FRAME_HEIGHT);
setTitle("Geometric Transformations");
getContentPane().setLayout(null);
setDefaultLookAndFeelDecorated(true);
grid = new GridPanel();
grid.setBounds(0,0,530,FRAME_HEIGHT);
this.add(grid);
top = new JTextField(); // parameter is size of input characters
top.setText("1 2 3");
top.setBounds(590, 150, 120, 25);
bottom = new JTextField(); // parameter is size of input characters
bottom.setText("5 6 7");
bottom.setBounds(590, 200, 120, 25);
numPoint = new JTextField();
numPoint.setText("Number of Points?");
numPoint.setBounds(550,200,200,25);
this.add(numPoint);
SubmitButton submit = new SubmitButton("Submit");
submit.setBounds(570, 250, 170, 25);
bpanel = new JPanel(new GridLayout(2,3));
bpanel.add(top);
bpanel.add(bottom);
bpanel.add(submit);
points = new JPanel(new GridLayout(2,2));
points.setBounds(540,250,265,60);
this.add(points);
bpanel.setBounds(550,100,200,70);
this.add(bpanel, BorderLayout.LINE_START);
Component[] a = points.getComponents();
System.out.println(a.length);
repaint();
}
class SubmitButton extends JButton implements ActionListener {
public SubmitButton(String title){
super(title);
addActionListener(this);
this.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
maxPoints = Integer.parseInt(numPoint.getText()) * 2;
points.removeAll();
for (int i=0; i<maxPoints; i++) {
JTextField textField = new JTextField();
points.add(textField);
}
points.validate(); // necessary when adding components to a JPanel
points.repaint();
// http://stackoverflow.com/questions/369823/java-gui-repaint-problem-solved
// What to Check:
// Things between commas are either spaces (which will be stripped later)
// or numbers!
// Pairs must match up!
}
}
public static void main(String[] args) {
// Schedule a job for the event-dispatching thread:
// creating and showing this application's GUI.
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
SODisplay display = new SODisplay();
display.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
display.setVisible(true);
}
});
}
class GridPanel extends JPanel {
// Or drop the offset and adjust the placement of the component
final int GRAPH_OFFSETX = 35;
final int GRAPH_OFFSETY = 60;
final int GRAPH_WIDTH = 500;
final int GRAPH_HEIGHT = 500;
final int GRAPH_INTERVAL = 20;
public GridPanel() {
}
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.WHITE);
g.fillRect(100, 100, 20, 30);
g.setColor(Color.BLACK);
genGraph(g, GRAPH_OFFSETX, GRAPH_OFFSETY, GRAPH_WIDTH, GRAPH_HEIGHT, GRAPH_INTERVAL);
}
public void genGraph (Graphics g, int x, int y, int width, int height, int interval) {
// draw background
int border = 5;
g.setColor(Color.BLACK);
width = width - (width % interval);
height = height - (height % interval);
for (int col=x; col <= x+width; col+=interval) {
g.drawLine(col, y, col, y+height);
}
for (int row=y; row <= y+height; row+=interval) {
g.drawLine(x, row, x+width, row);
}
}
}
}
That's just my test code in one file for simplicity, you might want to dissect it differently, of course.
Related
Im trying to code a simple 2D game. I have a Square that you can move with a/w/d. I got jumping working with a sort of gravity but now I cant get myself to land on a platform. I know how to detect collision between two things but even still idk what to do. My gravity always pulls me down until I reach groundLevel which is part of the problem. Here is my code so far. There's a lot of experimenting happing so its pretty messy.
import javax.swing.Timer;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.geom.*;
/**
* Custom Graphics Example: Using key/button to move a line left or right.
*/
public class PlatformingGame extends JFrame implements ActionListener, KeyListener{
// Name-constants for the various dimensions
public static final int CANVAS_WIDTH = 800;
public static final int CANVAS_HEIGHT = 400;
public static final Color LINE_COLOR = Color.BLACK;
public static final Color CANVAS_BACKGROUND = Color.WHITE;
public int GRAVITY = 10;
public int TERMINAL_VELOCITY = 300;
public int vertical_speed = 0;
public int jumpSpeed;
public int groundLevel = CANVAS_HEIGHT;
int Shapes;
private DrawCanvas canvas; // the custom drawing canvas (extends JPanel)
public enum STATE {
PLAYING,
PAUSED,
ONGROUND,
INAIR
};
JButton btnStartRestat, btnExit;
Timer timer;
Rectangle2D.Double guy, platform, platform2;
Shape[] shapeArr = new Shape[10];
int dx, dy;
/** Constructor to set up the GUI */
ArrayList myKeys = new ArrayList<Character>();
public static STATE gameState = STATE.PAUSED;
//public static STATE playerState = STATE.ONGROUND;
public PlatformingGame() {
dx = 3;
dy = 3;
guy = new Rectangle2D.Double( CANVAS_WIDTH/2 - 20, CANVAS_HEIGHT, 30, 20);
platform2 = new Rectangle2D.Double( CANVAS_WIDTH/4, CANVAS_HEIGHT/2+130, 50, 10);
platform = new Rectangle2D.Double( CANVAS_WIDTH/3, CANVAS_HEIGHT/2+50, 50, 10);
timer = new Timer(10, this);
// Set up a panel for the buttons
JPanel btnPanel = new JPanel();
// btnPanel.setPreferredSize(new Dimension(CANVAS_WIDTH/2, CANVAS_HEIGHT));
btnPanel.setLayout(new FlowLayout());
btnStartRestat = new JButton("Start/Restart");
btnExit = new JButton("Exit");
btnPanel.add(btnStartRestat);
btnPanel.add(btnExit);
btnStartRestat.addActionListener(this);
btnExit.addActionListener(this);
// Set up a custom drawing JPanel
canvas = new DrawCanvas();
canvas.setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));
// Add both panels to this JFrame
Container cp = getContentPane();
cp.setLayout(new BorderLayout());
cp.add(canvas, BorderLayout.CENTER);
cp.add(btnPanel, BorderLayout.SOUTH);
// "this" JFrame fires KeyEvent
addKeyListener(this);
requestFocus(); // set the focus to JFrame to receive KeyEvent
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Handle the CLOSE button
pack(); // pack all the components in the JFrame
setVisible(true); // show it
}
public void generateSpikes(){
Rectangle2D.Double spikes = null;
for (int i = 0; i < 10; i++) {
spikes = new Rectangle2D.Double (CANVAS_WIDTH - 300 + i*20 , CANVAS_HEIGHT - 30 , 20, 30);
shapeArr[i] = spikes;
}
}
public void actionPerformed(ActionEvent e)
{
if (e.getSource()==btnStartRestat)
{
generateSpikes();
dx = 3;
dy = 3;
guy = new Rectangle2D.Double( 100, CANVAS_HEIGHT - guy.height, 15, 30);
platform = new Rectangle2D.Double( CANVAS_WIDTH/3, CANVAS_HEIGHT/2+50, 50, 10);
platform2 = new Rectangle2D.Double( CANVAS_WIDTH/4, CANVAS_HEIGHT/2+130, 50, 10);
gameState = STATE.PLAYING;
}
else if (e.getSource()==btnExit)
{
// requestFocus(); // change the focus to JFrame to receive KeyEvent
}
else if (e.getSource()== timer){
if (isHitDetected(platform2, guy)){
// playerState = STATE.ONGROUND;
guy.y = platform2.y;
}
if (myKeys.contains('a')
&& (guy.x > 0)){
guy.x = guy.x - 5; }
if (myKeys.contains('d')
&& (guy.x < CANVAS_WIDTH - guy.width)){
guy.x = guy.x + 5; }
{
updateGuyPosition();
}
requestFocus();
canvas.repaint();
}
}
public void updateGuyPosition(){
double guyHeight = guy.height;
if (guy.x >= CANVAS_WIDTH - guy.width){
}
if(gameState == STATE.PLAYING) {
guy.y += jumpSpeed;
if (guy.y < groundLevel - guyHeight) {
// if(playerState == STATE.INAIR) {
jumpSpeed += 1;
}
// }
else {
// if(playerState == STATE.INAIR) {
//playerState = STATE.ONGROUND;
jumpSpeed = 0;
guy.y = groundLevel - guyHeight;
}
// }
if (myKeys.contains('w') == true && guy.y == groundLevel - guyHeight) {
jumpSpeed = -15;
// playerState = STATE.INAIR;
}
}
}
public static boolean isHitDetected(Shape shapeA, Shape shapeB) {
Area areaA = new Area(shapeA);
areaA.intersect(new Area(shapeB));
return !areaA.isEmpty();
}
public void keyPressed(KeyEvent evt) {
if (!myKeys.contains(evt.getKeyChar())){
myKeys.add(evt.getKeyChar());
}
}
public void keyReleased(KeyEvent evt) {
myKeys.remove(myKeys.indexOf(evt.getKeyChar()));
}
public void keyTyped(KeyEvent evt) {
}
/** The entry main() method */
public static void main(String[] args) {
PlatformingGame myProg = new PlatformingGame(); // Let the constructor do the job
myProg.timer.start();
}
/**
* DrawCanvas (inner class) is a JPanel used for custom drawing
*/
class DrawCanvas extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(CANVAS_BACKGROUND);
g.setColor(LINE_COLOR);
Graphics2D g2d = (Graphics2D)g;
if(gameState == STATE.PLAYING) {
g2d.fill(guy);
g.setColor(Color.lightGray);
g2d.fill(platform);
g2d.fill(platform2);
for (int i = 0; i < 10; i++) {
g2d.fill(shapeArr[i]);
}
}
if(gameState == STATE.PAUSED) {
g.drawString("Game Paused", CANVAS_WIDTH/2, CANVAS_HEIGHT/2);
}
}
}
}
I made a class that draws a piechart and this class extends JComponent. It exactly works like the way I want it to, except when I want make two instances of this class instead of one. The piechart that was created last only shows up. The other one won't. I printed the bounds of both charts to the console and I saw that the one that isn't showing has width = 0 and height = 0, but I did give a certain width and height at the declaration.
PieChart class
public class PieChart extends JComponent {
private static final long serialVersionUID = -5712412361082680298L;
private Rectangle bounds;
public ArrayList<PieSlice> slices = new ArrayList<PieSlice>();
PieChart(int x, int y, int width, int height) {
bounds = new Rectangle(x, y, width, height);
this.setBounds(bounds);
}
public void paint(Graphics g) {
drawPie((Graphics2D) g, bounds, slices);
}
void drawPie(Graphics2D g, Rectangle area, ArrayList<PieSlice> slices) {
double total = 0.0D;
for (int i = 0; i < slices.size(); i++) {
total += slices.get(i).value;
}
double curValue = 0.0D;
int startAngle = 0;
for (int i = 0; i < slices.size(); i++) {
startAngle = (int) (curValue * 360 / total);
int arcAngle = (int) (slices.get(i).value * 360 / total);
g.setColor(slices.get(i).color);
g.fillArc(area.x, area.y, area.width, area.height, startAngle, arcAngle);
curValue += slices.get(i).value;
}
}
public void addPieSlice(double value, Color color) {
PieSlice slice = new PieSlice(value, color);
slices.add(slice);
}
}
MainView class
public class MainView extends JFrame {
private static final long serialVersionUID = 1L;
private CarParkView carParkView;
public PieChart occupiedPieChart;
public PieChart subscribersPieChart;
public JPanel buttonPane;
public JButton resume;
public JButton pause;
public JButton plusHundredTicks;
public MainView(Model model, int numberOfFloors, int numberOfRows, int numberOfPlaces) {
this.setPreferredSize(new Dimension(1500,1000));
carParkView = new CarParkView(model, numberOfFloors, numberOfRows, numberOfPlaces);
occupiedPieChart = new PieChart(900, 100, 400, 400);
subscribersPieChart = new PieChart(900, 500, 400, 400);
buttonPane = new JPanel();
resume = new JButton("Resume");
pause = new JButton("Pause");
plusHundredTicks = new JButton("+100 ticks");
buttonPane.add(resume);
buttonPane.add(pause);
buttonPane.add(plusHundredTicks);
buttonPane.setBounds(0, 20, 1000, 100);
carParkView.setBounds(0, 100, 800, 500);
occupiedPieChart.addPieSlice(10, Color.WHITE);
occupiedPieChart.addPieSlice(90, Color.GREEN);
subscribersPieChart.addPieSlice(50, Color.WHITE);
subscribersPieChart.addPieSlice(50, Color.BLUE);
Container contentPane = getContentPane();
contentPane.add(buttonPane);
contentPane.add(subscribersPieChart);
contentPane.add(carParkView);
contentPane.add(occupiedPieChart);
pack();
setVisible(true);
updateView();
}
public void updateView() {
carParkView.updateView();
subscribersPieChart.repaint();
occupiedPieChart.repaint();
}
}
Note: This is my first Java - eclipse project, even though the solution is maybe quite easy I still have been staring at this for hours.
When i setSize of a jLabel, normally it grows towards bottom. How can i increase the height in positive y direction ?
After pressing init
Current Result
Expected result
My source code
private void initActionPerformed(java.awt.event.ActionEvent evt) {
int p = Integer.parseInt(abc[0].getText());
int q = Integer.parseInt(abc[1].getText());
int r = Integer.parseInt(abc[2].getText());
int s = Integer.parseInt(abc[3].getText());
int t = Integer.parseInt(abc[4].getText());
one.setSize(20, p*10 );
one.setBackground(Color.decode("#03A9F4"));
two.setSize(20, q*10 );
two.setBackground(Color.decode("#03A9F4"));
three.setSize(20, r*10 );
three.setBackground(Color.decode("#03A9F4"));
four.setSize(20, s*10 );
four.setBackground(Color.decode("#03A9F4"));
five.setSize(20, t*10 );
five.setBackground(Color.decode("#03A9F4"));
}
one,two,three are the label names.
abc is an array containing all the labels
You're finding out that Java considers positive y direction graphics to be down, which is in keeping with how computer monitors see y direction. Solutions include:
Figure out a maximum size, and subtract your y height from it to figure out where to start your JLabel.
Even better, don't use JLabels but draw within a JPanel's paintComponent, using the same calculations as above.
For example:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
#SuppressWarnings("serial")
public class GraphicsEg extends JPanel {
private static final int DATA_COLUMNS = 5;
private List<JSlider> sliders = new ArrayList<>();
private DrawPanel drawPanel = new DrawPanel(DATA_COLUMNS);
public GraphicsEg() {
JPanel sliderPanel = new JPanel(new GridLayout(1, 0, 5, 5));
SliderListener sliderListener = new SliderListener();
for (int i = 0; i < DATA_COLUMNS; i++) {
JSlider slider = new JSlider(0, 100, 50);
slider.setPaintLabels(true);
slider.setPaintTicks(true);
slider.setPaintTrack(true);
slider.setMajorTickSpacing(20);
slider.setMinorTickSpacing(5);
slider.setOrientation(SwingConstants.VERTICAL);
slider.addChangeListener(sliderListener);
sliders.add(slider);
sliderPanel.add(slider);
}
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
setLayout(new BorderLayout(5, 5));
add(drawPanel, BorderLayout.CENTER);
add(sliderPanel, BorderLayout.PAGE_END);
sliderValuesIntoDrawPanel();
}
private void sliderValuesIntoDrawPanel() {
int[] data = new int[DATA_COLUMNS];
for (int i = 0; i < data.length; i++) {
data[i] = sliders.get(i).getValue();
}
drawPanel.setData(data);
}
private class SliderListener implements ChangeListener {
#Override
public void stateChanged(ChangeEvent e) {
sliderValuesIntoDrawPanel();
}
}
private static void createAndShowGui() {
GraphicsEg mainPanel = new GraphicsEg();
JFrame frame = new JFrame("GraphicsEg");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
#SuppressWarnings("serial")
class DrawPanel extends JPanel {
private static final int PREF_W = 600;
private static final int PREF_H = 400;
private static final int PAD = 20;
private static final Color BORDER_COLOR = Color.BLUE;
private static final Color COLUMN_COLOR = Color.RED;
private static final double RELATIVE_COL_WIDTH = 2.0 / 3.0;
private int dataColumns = 0;
private int[] data;
public DrawPanel(int dataColumns) {
this.dataColumns = dataColumns;
data = new int[dataColumns];
setBorder(BorderFactory.createLineBorder(BORDER_COLOR));
}
public void setData(int[] data) {
this.data = data;
repaint();
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < data.length; i++) {
drawColumn(g, i, data[i]);
}
}
private void drawColumn(Graphics g, int index, int columnHeight) {
g.setColor(COLUMN_COLOR);
int width = (int) (RELATIVE_COL_WIDTH * (PREF_W - 2 * PAD) / dataColumns);
int x = PAD + (index * (PREF_W - 2 * PAD)) / dataColumns;
int height = (columnHeight * (PREF_H - 2 * PAD)) / 100;
int y = PREF_H - PAD - height;
g.fillRect(x, y, width, height);
}
}
In my code i generate randoms integer between 0 and 60 and i draw lines based on these.
I just want my lines fit the ordinate vertical line without touching my randoms integer... I guess it's kind of a mathematics problem but i'm really stuck here!
Here's my code first:
Windows.java:
public class Window extends JFrame{
Panel pan = new Panel();
JPanel container, north,south, west;
public JButton ip,print,cancel,start,ok;
JTextArea timeStep;
JLabel legend;
double time=0;
double temperature=0.0;
Timer chrono;
public static void main(String[] args) {
new Window();
}
public Window()
{
System.out.println("je suis là");
this.setSize(1000,400);
this.setLocationRelativeTo(null);
this.setResizable(false);
this.setTitle("Assignment2 - CPU temperature");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
container = new JPanel(new BorderLayout());
north = new JPanel();
north.setLayout(new BorderLayout());
ip = new JButton ("New");
north.add(ip, BorderLayout.WEST);
print = new JButton ("Print");
north.add(print,BorderLayout.EAST);
JPanel centerPanel = new JPanel();
centerPanel.add(new JLabel("Time Step (in s): "));
timeStep = new JTextArea("0.1",1,5);
centerPanel.add(timeStep);
start = new JButton("OK");
ListenForButton lForButton = new ListenForButton();
start.addActionListener(lForButton);
ip.addActionListener(lForButton);
print.addActionListener(lForButton);
centerPanel.add(start);
north.add(centerPanel, BorderLayout.CENTER);
west = new JPanel();
JLabel temp = new JLabel("°C");
west.add(temp);
container.add(north, BorderLayout.NORTH);
container.add(west,BorderLayout.WEST);
container.add(pan, BorderLayout.CENTER);
this.setContentPane(container);
this.setVisible(true);
}
private class ListenForButton implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource()==start)
{
time=Double.parseDouble(timeStep.getText());
System.out.println(time);
chrono = new Timer((int)(1000*time),pan);
chrono.start();
}
if(e.getSource()==ip)
{
JPanel options = new JPanel();
JLabel address = new JLabel("IP Address:");
JTextField address_t = new JTextField(15);
JLabel port = new JLabel("Port:");
JTextField port_t = new JTextField(5);
options.add(address);
options.add(address_t);
options.add(port);
options.add(port_t);
int result = JOptionPane.showConfirmDialog(null, options, "Please Enter an IP Address and the port wanted", JOptionPane.OK_CANCEL_OPTION);
if(result==JOptionPane.OK_OPTION)
{
System.out.println(address_t.getText());
System.out.println(port_t.getText());
}
}
if(e.getSource()==print)
{
chrono.stop();
}
}
}
}
Panel.java:
public class Panel extends JPanel implements ActionListener {
int rand;
int lastrand=0;
ArrayList<Integer> randL = new ArrayList<>();
ArrayList<Integer> tL = new ArrayList<>();
int lastT = 0;
Color red = new Color(255,0,0);
Color green = new Color(0,200,0);
Color blue = new Color (0,0,200);
Color yellow = new Color (200,200,0);
int max=0;
int min=0;
int i,k,inc = 0,j;
int total,degr,moyenne;
public Panel()
{
super();
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(new BasicStroke(1.8f));
g2.drawLine(20, 20, 20, this.getHeight()-50);
g2.drawLine(20, this.getHeight()-50, this.getWidth()-50, this.getHeight()-50);
g2.drawLine(20, 20, 15, 35);
g2.drawLine(20, 20, 25, 35);
g2.drawLine(this.getWidth()-50, this.getHeight()-50, this.getWidth()-65, this.getHeight()-45);
g2.drawLine(this.getWidth()-50, this.getHeight()-50, this.getWidth()-65, this.getHeight()-55);
g.drawString("10", 0, this.getHeight()-85);
g.drawString("20", 0, this.getHeight()-125);
g.drawString("30", 0, this.getHeight()-165);
g.drawString("40", 0, this.getHeight()-205);
g.drawString("50", 0, this.getHeight()-245);
g2.drawString("Maximum: ", 20, this.getHeight()-20);
g2.drawString(Integer.toString(max), 80, this.getHeight()-20);
g2.drawString("Minimum: ", 140, this.getHeight()-20);
g2.drawString(Integer.toString(min), 200, this.getHeight()-20);
g2.drawString("Average: ", 260, this.getHeight()-20);
g2.drawString(Integer.toString(moyenne), 320, this.getHeight()-20);
g2.setColor(red);
g2.drawLine(500, this.getHeight()-25, 540, this.getHeight()-25);
g2.setColor(new Color(0,0,0));
g2.drawString(": Maximum", 560, this.getHeight()-20);
g2.setColor(blue);
g2.drawLine(640, this.getHeight()-25, 680, this.getHeight()-25);
g2.setColor(new Color(0,0,0));
g2.drawString(": Minimum", 700, this.getHeight()-20);
g2.setColor(green);
g2.drawLine(780, this.getHeight()-25, 820, this.getHeight()-25);
g2.setColor(new Color(0,0,0));
g2.drawString(": Average", 840, this.getHeight()-20);
if(!randL.isEmpty()){
g2.setColor(red);
g2.drawLine(15, this.getHeight()-50-max, this.getWidth()-50,this.getHeight()-50-max);
g2.setColor(blue);
g2.drawLine(15, this.getHeight()-50-min, this.getWidth()-50,this.getHeight()-50-min);
g2.setColor(green);
g2.drawLine(15, this.getHeight()-50-moyenne, this.getWidth()-50,this.getHeight()-50-moyenne);
}
for(i = 0; i<tL.size(); i++){
int temp = randL.get(i);
int t = tL.get(i);
g2.setColor(new Color(0,0,0));
g2.drawLine(20+t, this.getHeight()-50-temp, 20+t, this.getHeight()-50);
// Ellipse2D circle = new Ellipse2D.Double();
//circle.setFrameFromCenter(20+t, this.getHeight()-50, 20+t+2, this.getHeight()-52);
}
for(j=0;j<5;j++)
{
inc=inc+40;
g2.setColor(new Color(0,0,0));
g2.drawLine(18, this.getHeight()-50-inc, 22, this.getHeight()-50-inc);
}
inc=0;
}
#Override
public void actionPerformed(ActionEvent e) {
rand = (int)(Math.random() * (60));
lastT += 80;
randL.add(rand);
tL.add(lastT);
Object obj = Collections.max(randL);
max = (int) obj;
Object obj2 = Collections.min(randL);
min = (int) obj2;
if(!randL.isEmpty()) {
degr = randL.get(k);
total += degr;
moyenne=total/randL.size();
}
k++;
if(randL.size()>=12)
{
randL.removeAll(randL);
tL.removeAll(tL);
lastT = 0;
k=0;
degr=0;
total=0;
moyenne=0;
}
repaint();
}
}
And here it what i gives me :
Sorry it's a real mess!
Any thoughts ?
Thanks.
You need to stop working with absolute/magical values, and start using the actual values of the component (width/height).
The basic problem is a simple calculation which takes the current value divides it by the maximum value and multiples it by the available width of the allowable area
int length = (value / max) * width;
value / max generates a percentage value of 0-1, which you then use to calculate the percentage of the available width of the area it will want to use.
The following example places a constraint (or margin) on the available viewable area, meaning all the lines need to be painted within that area and not use the entire viewable area of the component
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class DrawLine {
public static void main(String[] args) {
new DrawLine();
}
public DrawLine() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int margin = 20;
int width = getWidth() - (margin * 2);
int height = getHeight() - (margin * 2);
int x = margin;
for (int index = 0; index < 4; index++) {
int y = margin + (int)(((index / 3d) * height));
int length = (int)(((index + 1) / 4d) * width);
g2d.drawLine(x, y, x + length, y);
}
g2d.dispose();
}
}
}
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);
}
}