JScrollPane with rulers didn't work - java

I've tried to run the example found in Java Swing 2nd Edition 7.1.3 ScrollPaneLayout. The image and the scroll have worked just fine, but the ruler hasn't. Here's my code:
public class ScrollPaneLayoutDemo extends JFrame{
JLabel label = new JLabel(new ImageIcon("img.jpg"));
public ScrollPaneLayoutDemo() {
super("ScrollPaneLayout Demo");
JScrollPane jsp = new JScrollPane(label);
JLabel[] corners = new JLabel[4];
for(int i=0; i<4; i++)
{
corners[i] = new JLabel();
corners[i].setBackground(Color.YELLOW);
corners[i].setOpaque(true);
corners[i].setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2), BorderFactory.createLineBorder(Color.RED, 1)));
}
JLabel rowheader = new JLabel() {
Font f = new Font("Serif", Font.ITALIC | Font.BOLD, 10);
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Rectangle r = g.getClipBounds();
g.setFont(f);
g.setColor(Color.RED);
for (int i = 50 - (r.y % 50); i < r.height; i += 50) {
g.drawLine(0, r.y + i, 3, r.y + i);
g.drawString("" + (r.y + i), 6, r.y + i + 3);
}
}
public Dimension getPreferredSize()
{
return new Dimension(25, (int) label.getPreferredSize().getHeight());
}
};
rowheader.setBackground(Color.YELLOW);
rowheader.setOpaque(true);
JLabel columnheader = new JLabel() {
Font f = new Font("Serif", Font.ITALIC | Font.BOLD, 10);
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Rectangle r = g.getClipBounds();
g.setFont(f);
g.setColor(Color.RED);
for (int i = 50 - (r.x % 50); i < r.width; i += 50)
{
g.drawLine(r.x + i, 0, r.x + i, 3);
g.drawString("" + (r.x + i), r.x + i - 10, 16);
}
}
public Dimension getPreferredSize()
{
return new Dimension((int) label.getPreferredSize().getWidth(),25);
}
};
columnheader.setBackground(Color.YELLOW);
columnheader.setOpaque(true);
jsp.setRowHeaderView(rowheader);
jsp.setColumnHeaderView(columnheader);
jsp.setCorner(JScrollPane.LOWER_LEFT_CORNER, corners[0]);
jsp.setCorner(JScrollPane.LOWER_RIGHT_CORNER, corners[1]);
jsp.setCorner(JScrollPane.UPPER_LEFT_CORNER, corners[2]);
jsp.setCorner(JScrollPane.UPPER_RIGHT_CORNER, corners[3]);
getContentPane().add(jsp, BorderLayout.CENTER);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 300);
setVisible(true);
}
public static void main(String[] args) {
new JScrollPaneDemo();
}
}
If anyone could help me with this issue I appreciate.

Dimension from child must be greater than JViewports Dimension (visible rectangle from JScrollPane), then JScrollBars or custom decorations can be visible, more in Oracle tutorial How to use ScrollPanes
search for #Annotations
e.g.
no idea why but I can't add image here :-)
from
import java.awt.*;
import javax.swing.*;
public class ScrollPaneLayoutDemo extends JFrame {
private static final long serialVersionUID = 1L;
private JLabel label = new JLabel(new ImageIcon("img.jpg")) {
#Override
public Dimension getPreferredSize() {
return new Dimension(new Dimension(800, 600));/*icon.getIconWidth(), icon.getIconHeight()*/
}
};
public ScrollPaneLayoutDemo() {
super("ScrollPaneLayout Demo");
label.setPreferredSize(new Dimension(800, 600));
JScrollPane jsp = new JScrollPane(label);
JLabel[] corners = new JLabel[4];
for (int i = 0; i < 4; i++) {
corners[i] = new JLabel();
corners[i].setBackground(Color.YELLOW);
corners[i].setOpaque(true);
corners[i].setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2), BorderFactory.createLineBorder(Color.RED, 1)));
}
JLabel rowheader = new JLabel() {
private static final long serialVersionUID = 1L;
Font f = new Font("Serif", Font.ITALIC | Font.BOLD, 10);
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Rectangle r = g.getClipBounds();
g.setFont(f);
g.setColor(Color.RED);
for (int i = 50 - (r.y % 50); i < r.height; i += 50) {
g.drawLine(0, r.y + i, 3, r.y + i);
g.drawString("" + (r.y + i), 6, r.y + i + 3);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(25, (int) label.getPreferredSize().getHeight());
}
};
rowheader.setBackground(Color.YELLOW);
rowheader.setOpaque(true);
JLabel columnheader = new JLabel() {
private static final long serialVersionUID = 1L;
Font f = new Font("Serif", Font.ITALIC | Font.BOLD, 10);
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Rectangle r = g.getClipBounds();
g.setFont(f);
g.setColor(Color.RED);
for (int i = 50 - (r.x % 50); i < r.width; i += 50) {
g.drawLine(r.x + i, 0, r.x + i, 3);
g.drawString("" + (r.x + i), r.x + i - 10, 16);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension((int) label.getPreferredSize().getWidth(), 25);
}
};
columnheader.setBackground(Color.YELLOW);
columnheader.setOpaque(true);
jsp.setRowHeaderView(rowheader);
jsp.setColumnHeaderView(columnheader);
jsp.setCorner(JScrollPane.LOWER_LEFT_CORNER, corners[0]);
jsp.setCorner(JScrollPane.LOWER_RIGHT_CORNER, corners[1]);
jsp.setCorner(JScrollPane.UPPER_LEFT_CORNER, corners[2]);
jsp.setCorner(JScrollPane.UPPER_RIGHT_CORNER, corners[3]);
getContentPane().add(jsp, BorderLayout.CENTER);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 300);
setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new ScrollPaneLayoutDemo();
}
});
}
}

Related

Changing the frame's display after every interval, like an animation

How can I use repaint here, that it changes the display after some interval, like an animation?
Ouput:
(Like initially and randomly it is) this-1 (after some short interval and randomly it changes to) this-2 and continued...
import java.awt.*;
import java.util.Random;
import javax.swing.*;
class MatrixPanel extends JPanel {
private final int sqW = 15;
private final int sqH = 15;
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
#Override
public void paintComponent(Graphics g) {
Random rand = new Random();
for (int i = 0; i < 300; i += this.sqW) {
for (int j = 0; j < 300; j += this.sqH) {
if (rand.nextInt(2) == 1) {
g.setColor(Color.BLACK);
} else {
g.setColor(Color.GRAY);
}
g.fillRect(i, j, this.sqW, this.sqH);
g.setColor(Color.BLACK);
g.drawRect(i, j, this.sqW, this.sqH);
}
}
}
}
class GameOfLifeGUI extends JFrame {
public GameOfLifeGUI() {
JSplitPane splitPane = new JSplitPane();
/*Panels*/
JPanel topPanel = new JPanel();
JPanel bottomPanel = new JPanel();
/*Label - 1*/
JLabel generationLabel = new JLabel("GenerationLabel");
generationLabel.setText("Generation #");
generationLabel.setFont(new Font("Comic Sans MS", Font.PLAIN, 14));
generationLabel.setBounds(10, 5, 300, 20);
/*Label - 2*/
JLabel aliveLabel = new JLabel("AliveLabel");
aliveLabel.setText("Alive: ");
aliveLabel.setFont(new Font("Comic Sans MS", Font.PLAIN, 14));
aliveLabel.setBounds(10, 25, 300, 20);
topPanel.setLayout(null);
topPanel.add(generationLabel);
topPanel.add(aliveLabel);
bottomPanel.add(new MatrixPanel());
setPreferredSize(new Dimension(315, 405));
getContentPane().setLayout(new GridLayout());
getContentPane().add(splitPane);
splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
splitPane.setDividerLocation(50);
splitPane.setTopComponent(topPanel);
splitPane.setBottomComponent(bottomPanel);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
pack();
}
public static void main(String[] args) {
new GameOfLifeGUI().setVisible(true);
}
}
Specifically not repaint, if there are other components that I can use and meet my requirements will be most welcome.
Thank you.
You don't want to do the following:
public void paintComponent(Graphics g) {
Random rand = new Random();
for (int i = 0; i < 300; i += this.sqW) {
for (int j = 0; j < 300; j += this.sqH) {
if (rand.nextInt(2) == 1) {
g.setColor(Color.BLACK);
} else {
g.setColor(Color.GRAY);
}
g.fillRect(i, j, this.sqW, this.sqH);
g.setColor(Color.BLACK);
g.drawRect(i, j, this.sqW, this.sqH);
}
}
}
Since painting is done on the EDT, you need to keep your processing to a minimum, otherwise performance will suffer and you may even lock up your application.
Use a Swing timer and create the image in a BufferedImage object. BufferedImages provide a graphics context so you can use the same methods you are using in paintComponent.
You can set the timer interval to whatever works for you and then issue a repaint when the image is created. So it could look similar to the following:
final BufferedImage image = new BufferedImage(300,300,BufferedImage.TYPE_INT_RGB);
...
Timer timer = new Timer(0, ae->createImage());
timer.setDelay(300);
timer.start();
...
public void createImage(BufferedImage image) {
Random rand = new Random();
Graphics g = image.getGraphics();
for (int i = 0; i < 300; i += this.sqW) {
for (int j = 0; j < 300; j += this.sqH) {
if (rand.nextInt(2) == 1) {
g.setColor(Color.BLACK);
} else {
g.setColor(Color.GRAY);
}
g.fillRect(i, j, this.sqW, this.sqH);
g.setColor(Color.BLACK);
g.drawRect(i, j, this.sqW, this.sqH);
}
}
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
// Image observer not required so it can be set to null.
g.drawImage(image, 0,0, null);
}
Finally, you need to set your MatrixPanel size large enough to hold the image. Probably 300 x 300.

I want to put the game on a JPane instead of it being on a JFrame so that I can access it though the use of the GUI however it wont work

Cannot put my game into the GUI without there being issues. When starting the GUI, it shows the game. It glitches out and only fixes after pressing on of the buttons. However the buttons are hidden unless you put your mouse over it. Here is the code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.util.*;
public class BBSays extends JFrame implements ActionListener, MouseListener
{
private BufferedImage image;
public static BBSays bbsays;
public Renderer renderer;
public static final int WIDTH = 800, HEIGHT = 800;
public int flashed = 0, glowTime, dark, ticks, indexPattern;
public boolean creatingPattern = true;
public ArrayList<Integer> pattern;
public Random random;
private boolean gameOver;
private JPanel game;
JFrame frame = new JFrame("BB8 Says");
private JPanel menu;
private JPanel credits;
ImageIcon bbegif = new ImageIcon("tumblr_o0c57n9gfv1tha1vgo1_r3_250.gif");
public BBSays()
{
Timer timer = new Timer(20, this);
renderer = new Renderer();
frame.setSize(WIDTH +7, HEIGHT +30);
frame.setVisible(true);
frame.addMouseListener(this);
frame.add(renderer);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE );
start();
timer.start();
menu = new JPanel();
credits = new JPanel();
game = new JPanel();
menu.setBackground(Color.yellow);
credits.setBackground(Color.yellow);
game.setBackground(Color.yellow);
JButton button = new JButton("Start");
JButton button2 = new JButton("Exit");
JButton button4 = new JButton("Start");
JLabel greet = new JLabel(" Welcome to BB8 Says");
JLabel jif = new JLabel(bbegif);
JLabel jif2 = new JLabel(bbegif);
JLabel saus = new JLabel("BB8 Image: https://49.media.tumblr.com/7ba3be87bff2efc009e9cfa889d46b4e/tumblr_o0c57n9gfv1tha1vgo1_r3_250.gif");
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
frame.setContentPane(game);
frame.invalidate();
frame.validate();
};
});
button2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
System.exit(0);
};
});
menu.setLayout(new GridLayout(2,2));
menu.add(jif2);
menu.add(greet);
menu.add(jif);
menu.add(button);
menu.add(button6);
menu.add(button2);
frame.setVisible(true);
}
private class MenuAction implements ActionListener {
private JPanel panel;
private MenuAction(JPanel pnl) {
this.panel = pnl;
}
#Override
public void actionPerformed(ActionEvent e) {
changePanel(panel);
}
}
private void changePanel(JPanel panel) {
getContentPane().removeAll();
getContentPane().add(panel, BorderLayout.CENTER);
getContentPane().doLayout();
update(getGraphics());
}
public void start()
{
random = new Random();
pattern = new ArrayList<Integer>();
indexPattern = 0;
dark = 2;
flashed = 0;
ticks = 0;
}
public static void main(String[] args)
{
bbsays = new BBSays();
}
#Override
public void actionPerformed(ActionEvent e)
{
ticks++;
if (ticks % 20 == 0)
{
flashed = 0;
if (dark >= 0)
{
dark--;
}
}
if (creatingPattern)
{
if (dark <= 0)
{
if (indexPattern >= pattern.size())
{
flashed = random.nextInt(40) % 4 + 1;
pattern.add(flashed);
indexPattern = 0;
creatingPattern = false;
}
else
{
flashed = pattern.get(indexPattern);
indexPattern++;
}
dark = 2;
}
}
else if (indexPattern == pattern.size())
{
creatingPattern = true;
indexPattern = 0;
dark = 2;
}
renderer.repaint();
}
public void paint(Graphics2D g)
{
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(Color.yellow);
g.fillRect(0, 0, WIDTH, HEIGHT);
if (flashed == 1)
{
g.setColor(Color.blue);
}
else
{
g.setColor(Color.blue.darker());
}
g.fillRect(0, 0, WIDTH/2, HEIGHT/2);
if (flashed == 2)
{
g.setColor(Color.green);
}
else
{
g.setColor(Color.green.darker());
}
g.fillRect(WIDTH/2, 0, WIDTH/2, HEIGHT/2);
if (flashed == 3)
{
g.setColor(Color.orange);
}
else
{
g.setColor(Color.orange.darker());
}
g.fillRect(0, HEIGHT/2, WIDTH/2, HEIGHT/2);
if (flashed == 4)
{
g.setColor(Color.gray);
}
else
{
g.setColor(Color.gray.darker());
}
g.fillRect(WIDTH/2, HEIGHT/2, WIDTH/2, HEIGHT/2);
g.setColor(Color.BLACK);
g.fillRoundRect(220, 220, 350, 350, 300, 300);
g.fillRect(WIDTH/2 - WIDTH/14, 0, WIDTH/7, HEIGHT);
g.fillRect(0, WIDTH/2 - WIDTH/12, WIDTH, HEIGHT/7);
g.setColor(Color.yellow);
g.setStroke(new BasicStroke(200));
g.drawOval(-100, -100, WIDTH+200, HEIGHT+200);
g.setColor(Color.black);
g.setStroke(new BasicStroke(5));
g.drawOval(0, 0, WIDTH, HEIGHT);
if (gameOver)
{
g.setColor(Color.WHITE);
g.setFont(new Font("Comic Sans", 1, 80));
g.drawString("You let", WIDTH / 2 - 140, HEIGHT / 2 - 70);
g.drawString("down BB8 :(", WIDTH / 2 - 220, HEIGHT / 2 );
g.drawString("Try again!", WIDTH / 2 - 195, HEIGHT / 2 + 80);
}
else
{
g.setColor(Color.WHITE);
g.setFont(new Font("Ariel", 1, 144));
g.drawString(indexPattern + "/" + pattern.size(), WIDTH / 2 - 100, HEIGHT / 2 + 42);
}
}
#Override
public void mousePressed(MouseEvent e)
{
int x = e.getX(), y = e.getY();
if (!creatingPattern && !gameOver)
{
if (x>0 && x<WIDTH/2 && y>0 && y<HEIGHT/2)
{
flashed = 1;
ticks = 1;
}
else if (x>WIDTH/2 && x<WIDTH && y>0 && y<HEIGHT/2)
{
flashed = 2;
ticks = 1;
}
else if (x>0 && x<WIDTH/2 && y>HEIGHT/2 && y<HEIGHT)
{
flashed = 3;
ticks = 1;
}
else if (x>WIDTH/2 && x<WIDTH && y>HEIGHT/2 && y<HEIGHT)
{
flashed = 4;
ticks = 1;
}
if (flashed != 0)
{
if (pattern.get(indexPattern)==flashed)
{
indexPattern++;
}
else
{
gameOver = true;
}
}
else
{
start();
gameOver = true;
}
}
else if (gameOver)
{
start();
gameOver = false;
}
}
Here is the code for the renderer class:
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
public class Renderer extends JPanel
{
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
if (BBSays.bbsays != null)
{
BBSays.bbsays.paint((Graphics2D) g);
}
}
}
I think that the issue is here as I use the super. method and want to put the graphics on the game JPanel in the main code. I have tried many ways of doing this but I am not able to put the game on a JPanel.
If you can help it is greatly appreciated.

Trying to solve a proportionnality issue here

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();
}
}
}

setBackground does not works on First time but on Second, Why?

I have seen this examlpe in a book , and is working fine but the only problem coming up is that the Background Does not turns black on First Call to Paint, When clearCounter become == 5, and then the screen is Cleared and again when Painting Starts, then the Background is turned Black.
public class apletprg extends JApplet implements ActionListener
{
int clearCounter;
Timer t;
public void init(){
setBackground(Color.black);
clearCounter = 0;
Timer t = new Timer(1000, this);
t.start();
}
public void paint(Graphics g)
{
setBackground(Color.black);
clearCounter++;
Graphics2D g2 = (Graphics2D) g;
if (clearCounter == 5){
g2.clearRect(0, 0, 500, 400);
clearCounter=0;
}
for (int i = 1; i <= 40; i++) {
Color c = chooseColor();
g2.setColor(c);
Font f = chooseFont();
g2.setFont(f);
drawJava(g2);
}
}
public void actionPerformed(ActionEvent ae){
repaint();
}
public Color chooseColor(){
int r= (int) (Math.random() * 255);
int g= (int) (Math.random() * 255);
int b= (int) (Math.random() * 255);
Color c = new Color(r,g,b);
return c;
}
public Font chooseFont(){
int fontChoice = (int) (Math.random() * 4) + 1;
Font f = null;
switch (fontChoice) {
case 1: f = new Font("Serif", Font.BOLD + Font.ITALIC, 20);break;
case 2: f = new Font("SansSerif", Font.PLAIN, 17);break;
case 3: f = new Font("Monospaced", Font.ITALIC, 23);break;
case 4: f = new Font("Dialog", Font.ITALIC, 30);break;
}
return f;
}
public void drawJava(Graphics2D g2){
int x = (int) (Math.random() * 500);
int y = (int) (Math.random() * 400);
g2.drawString("Adnan", x, y);
}
}
I Know that the Init () is called only once at the Start , but Why is that not able to change the Background at start?
In your init method replace setBackground(Color.black) with getContentPane().setBackground(Color.black)
And add super.paint(g) as the first line in your paint method.
Otherwise if you don't want to use Swing features then go ahead and import java.applet.Applet and make you class extend Applet instead of JApplet
public class NewClass extends JApplet implements ActionListener {
int clearCounter;
Timer t;
public void init() {
getContentPane().setBackground(Color.black);
repaint();
clearCounter = 0;
//t = new Timer("1000", true);
}
public void paint(Graphics g) {
super.paint(g);
setBackground(Color.black);
clearCounter++;
Graphics2D g2 = (Graphics2D) g;
if (clearCounter == 5) {
g2.clearRect(0, 0, 500, 400);
clearCounter = 0;
}
for (int i = 1; i <= 40; i++) {
Color c = chooseColor();
g2.setColor(c);
Font f = chooseFont();
g2.setFont(f);
drawJava(g2);
}
}
#Override
public void actionPerformed(ActionEvent ae) {
repaint();
}
public Color chooseColor() {
int r = (int) (Math.random() * 255);
int g = (int) (Math.random() * 255);
int b = (int) (Math.random() * 255);
Color c = new Color(r, g, b);
return c;
}
public Font chooseFont() {
int fontChoice = (int) (Math.random() * 4) + 1;
Font f = null;
switch (fontChoice) {
case 1:
f = new Font("Serif", Font.BOLD + Font.ITALIC, 20);
break;
case 2:
f = new Font("SansSerif", Font.PLAIN, 17);
break;
case 3:
f = new Font("Monospaced", Font.ITALIC, 23);
break;
case 4:
f = new Font("Dialog", Font.ITALIC, 30);
break;
}
return f;
}
public void drawJava(Graphics2D g2) {
int x = (int) (Math.random() * 500);
int y = (int) (Math.random() * 400);
g2.drawString("Adnan", x, y);
}
}
If you want to execute super.paint() only once add a boolean variable in your class
boolean firstTime = true;
In paint()
if(firstTime) {
super.paint(g);
firstTime = false;
}
Resolved the ProbleBy Just Adding One more Variable and Calling the ClearRect() at the Start of painting and to ensure that This will be Called only once , by the Help of Newly Added Variable.
public void init(){
setBackground(Color.black);
clearCounter = 0;
Timer t = new Timer(1000, this);
t.start();
check = 0; <------------ New Variable
}
public void paint(Graphics g)
{
if (check==0){
g.clearRect(0, 0, 500, 400); <------------ To Ensure That it will Excute Only Once , beacuse check is incremented later in Code
}
clearCounter++;
check++;
Graphics2D g2 = (Graphics2D) g;
if (clearCounter == 5){
g2.clearRect(0, 0, 500, 400);
clearCounter=0;
}
for (int i = 1; i <= 40; i++) {
Color c = chooseColor();
g2.setColor(c);
Font f = chooseFont();
g2.setFont(f);
drawJava(g2);
}
}

repaint problem

I have a problem with my repaint in the method move. I dont know what to doo, the code is below
import java.awt.*;
import java.io.*;
import java.text.*;
import java.util.*;
import javax.sound.sampled.*;
import javax.swing.*;
import javax.swing.Timer;
import java.awt.event.*;
import java.lang.*;
public class bbb extends JPanel
{
public Stack<Integer> stacks[];
public JButton auto, jugar, nojugar;
public JButton ok, ok2;
public JLabel info = new JLabel("Numero de Discos: ");
public JLabel instruc = new JLabel("Presiona la base de las torres para mover las fichas");
public JLabel instruc2 = new JLabel("No puedes poner una pieza grande sobre una pequenia!");
public JComboBox numeros = new JComboBox();
public JComboBox velocidad = new JComboBox();
public boolean seguir = false, parar = false, primera = true;
public int n1, n2, n3;
public int click1 = 0;
public int opcion = 1, tiempo = 50;
public int op = 1, continuar = 0, cont = 0;
public int piezas = 0;
public int posx, posy;
public int no;
public bbb() throws IOException
{
stacks = new Stack[3];
stacks[0] = new Stack<Integer>();
stacks[1] = new Stack<Integer>();
stacks[2] = new Stack<Integer>();
setPreferredSize(new Dimension(1366, 768));
ok = new JButton("OK");
ok.setBounds(new Rectangle(270, 50, 70, 25));
ok.addActionListener(new okiz());
ok2 = new JButton("OK");
ok2.setBounds(new Rectangle(270, 50, 70, 25));
ok2.addActionListener(new vel());
add(ok2);
ok2.setVisible(false);
auto = new JButton("Automatico");
auto.setBounds(new Rectangle(50, 80, 100, 25));
auto.addActionListener(new a());
jugar = new JButton("PLAY");
jugar.setBounds(new Rectangle(100, 100, 70, 25));
jugar.addActionListener(new play());
nojugar = new JButton("PAUSE");
nojugar.setBounds(new Rectangle(100, 150, 70, 25));
nojugar.addActionListener(new stop());
setLayout(null);
info.setBounds(new Rectangle(50, 50, 170, 25));
info.setForeground(Color.white);
instruc.setBounds(new Rectangle(970, 50, 570, 25));
instruc.setForeground(Color.white);
instruc2.setBounds(new Rectangle(970, 70, 570, 25));
instruc2.setForeground(Color.white);
add(instruc);
add(instruc2);
add(jugar);
add(nojugar);
jugar.setVisible(false);
nojugar.setVisible(false);
add(info);
info.setVisible(false);
add(ok);
ok.setVisible(false);
add(auto);
numeros.setBounds(new Rectangle(210, 50, 50, 25));
numeros.addItem(1);
numeros.addItem(2);
numeros.addItem(3);
numeros.addItem(4);
numeros.addItem(5);
numeros.addItem(6);
numeros.addItem(7);
numeros.addItem(8);
numeros.addItem(9);
numeros.addItem(10);
add(numeros);
numeros.setVisible(false);
velocidad.setBounds(new Rectangle(150, 50, 100, 25));
velocidad.addItem("Lenta");
velocidad.addItem("Intermedia");
velocidad.addItem("Rapida");
add(velocidad);
velocidad.setVisible(false);
}
public void Mover(int origen, int destino)
{
for (int i = 0; i < 3; i++)
{
System.out.print("stack " + i + ": ");
for (int n : stacks[i])
{
System.out.print(n + ";");
}
System.out.println("");
}
System.out.println("de <" + origen + "> a <" + destino + ">");
stacks[destino].push(stacks[origen].pop());
System.out.println("");
this.validate();
this.repaint();
}
public void hanoi(int origen, int destino, int cuantas)
{
while (parar)
{
}
if (cuantas <= 1)
{
Mover(origen, destino);
}
else
{
hanoi(origen, 3 - (origen + destino), cuantas - 1);
Mover(origen, destino);
hanoi(3 - (origen + destino), destino, cuantas - 1);
}
}
public void paintComponent(Graphics g)
{
ImageIcon fondo = new ImageIcon("fondo.jpg");
g.drawImage(fondo.getImage(), 0, 0, 1366, 768, null);
g.setColor(new Color((int) (Math.random() * 254),
(int) (Math.random() * 255),
(int) (Math.random() * 255)));
g.fillRect(0, 0, 100, 100);
g.setColor(Color.white);
g.fillRect(150, 600, 250, 25);
g.fillRect(550, 600, 250, 25);
g.fillRect(950, 600, 250, 25);
g.setColor(Color.red);
g.fillRect(270, 325, 10, 275);
g.fillRect(270 + 400, 325, 10, 275);
g.fillRect(270 + 800, 325, 10, 275);
int x, y, top = 0;
g.setColor(Color.yellow);
x = 150;
y = 580;
for (int ii : stacks[0])
{
g.fillRect(x + ((ii * 125) / 10), y - (((ii) * 250) / 10), ((10 - ii) * 250) / 10, 20);
}
x = 550;
y = 580;
for (int ii : stacks[1])
{
g.fillRect(x + ((ii * 125) / 10), y - (((ii) * 250) / 10), ((10 - ii) * 250) / 10, 20);
}
x = 950;
y = 580;
for (int ii : stacks[2])
{
g.fillRect(x + ((ii * 125) / 10), y - (((ii) * 250) / 10), ((10 - ii) * 250) / 10, 20);
}
System.out.println("ENTRO");
setOpaque(false);
}
private class play implements ActionListener //manual
{
public void actionPerformed(ActionEvent algo)
{
parar = false;
if (primera = true)
{
hanoi(0, 2, no);
primera = false;
}
}
}
private class stop implements ActionListener //manual
{
public void actionPerformed(ActionEvent algo)
{
parar = true;
}
}
private class vel implements ActionListener //manual
{
public void actionPerformed(ActionEvent algo)
{
if (velocidad.getSelectedItem() == "Lenta")
{
tiempo = 150;
}
else if (velocidad.getSelectedItem() == "Intermedia")
{
tiempo = 75;
}
else
{
tiempo = 50;
}
ok2.setVisible(false);
jugar.setVisible(true);
nojugar.setVisible(true);
}
}
private class a implements ActionListener //auto
{
public void actionPerformed(ActionEvent algo)
{
auto.setVisible(false);
info.setVisible(true);
numeros.setVisible(true);
ok.setVisible(true);
op = 3;
}
}
private class okiz implements ActionListener //ok
{
public void actionPerformed(ActionEvent algo)
{
no = Integer.parseInt(numeros.getSelectedItem().toString());
piezas = no;
if (no > 0 && no < 11)
{
info.setVisible(false);
numeros.setVisible(false);
ok.setVisible(false);
for (int i = no; i > 0; i--)
{
stacks[0].push(i);
}
opcion = 2;
if (op == 3)
{
info.setText("Velocidad: ");
info.setVisible(true);
velocidad.setVisible(true);
ok2.setVisible(true);
}
}
else
{
}
repaint();
}
}
}
the code of the other class that calls the one up is below:
import java.awt.*;
import java.io.*;
import java.net.URL;
import javax.imageio.*;
import javax.swing.*;
import javax.swing.border.*;
import java.lang.*;
import java.awt.event.*;
public class aaa extends JPanel
{
private ImageIcon Background;
private JLabel fondo;
public static void main(String[] args) throws IOException
{
JFrame.setDefaultLookAndFeelDecorated(true);
final JPanel cp = new JPanel(new BorderLayout());
JFrame frame = new JFrame ("Torres de Hanoi");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.setSize(550,550);
frame.setVisible(true);
bbb panel = new bbb();
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
}
}
Assuming that you see the progress in the println statements but not on the screen, it is because a call to repaint is not synchronous. Swing has a special thread for handling UI - called Event Dispatch Thread. A call to repaint is handled by that thread, but asynchronously - after all the current events scheduled on that thread have been processed.
When you call hanoi in your actionPerformed, that is done on the same UI thread. What happens is that until your recursion is fully done, repaint() calls are just queued. Once the recursion completes (and all stacks have been moved in the model), the UI thread processes all repaint() requests, painting - what i assume - the final state.
What you need to do is to separate the model processing into a separate worker thread. On every recursion step, issue a repaint() call and sleep for a few hundred milliseconds. This will allow the UI thread to repaint the current state of the model and let the user actually trace the progress.

Categories

Resources