Rotating Poly with transformation matrix.Figure is getting deformed - java

I'm relatively new in Java and I have a task to realize the rotation of a figure drawn from random points. The realization has to be written by means of "naked logic", so AffineTransform tools is not an option in this case. And I got stuck in a moment where I suppose to translate shape to origin in order to perform rotation. I racked my brains, surfed on the internet but couldn't succeed with the solution. There is already one topic with a similar issue, tho there it was about rectangles translation, so it hasn't worked for me. Maybe someone could help with this.
public class Frame extends JFrame {
private JButton polyBtn = new JButton("Draw/Redraw Poly");
private JButton rotationBtn = new JButton("Rotate");
private JSpinner polySpn = new JSpinner(new SpinnerNumberModel(3,3,10,1));
private JSpinner angleSpn = new JSpinner(new SpinnerNumberModel(0,0,360,1));
private JPanel panel = new JPanel();
private JPanel controlPanel = new JPanel();
private JLabel polyLbl = new JLabel("Choose number of corners");
private JLabel angleLbl = new JLabel("Choose angle of rotation");
private int cornerAmount , degree ;
private boolean figureIsDrawed = false;
Random r = new Random();
Polygon poly = new Polygon();
Polygon editedPoly = new Polygon();
public Frame() {
super("Rotate Object");
setBounds(100, 100, 500, 250);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container container = this.getContentPane();
container.setLayout(new BorderLayout());
setVisible(true);
setLocationRelativeTo(null);
setResizable(false);
polyBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
cornerAmount = (int) polySpn.getValue();
drawPoly(cornerAmount);
}});
rotationBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
degree = (int) angleSpn.getValue();
rotateShape(degree);
}});
panel.setPreferredSize(new Dimension(350,250));
panel.setBackground(Color.ORANGE);
panel.setBorder(BorderFactory.createLineBorder(Color.black,3));
controlPanel.setBorder(BorderFactory.createLineBorder(Color.BLUE, 2));
controlPanel.setLayout(new GridLayout(6,0,0,0));
polyLbl.setFont(polyLbl.getFont().deriveFont(10.0f));
angleLbl.setFont(angleLbl.getFont().deriveFont(10.0f));
controlPanel.add(polyLbl);
controlPanel.add(polySpn);
controlPanel.add(polyBtn);
controlPanel.add(angleLbl);
controlPanel.add(angleSpn);
controlPanel.add(rotationBtn);
container.add(controlPanel,BorderLayout.CENTER);
container.add(panel,BorderLayout.EAST);
}
private void drawPoly(int corners) {
Graphics g = panel.getGraphics();
int panelWidth = panel.getWidth();
int panelHeight = panel.getHeight();
if(figureIsDrawed) {
poly.reset();
repaint();
figureIsDrawed = false;
}else {
poly.addPoint(panelWidth/2, panelHeight/2);
System.out.println(poly.xpoints[0]);
System.out.println(poly.ypoints[0]);
for(int i = 0 ; i < corners-1 ; i++) {
poly.addPoint(r.nextInt(panelWidth), r.nextInt(panelHeight));
}
g.drawPolygon(poly);
figureIsDrawed = true;
}
}
private void rotateShape(int degree) {
Graphics g = panel.getGraphics();
int[] xCord = poly.xpoints;
int[] yCord = poly.ypoints;
double rads = degree * (Math.PI/180);
double sin = Math.sin(rads);
double cos = Math.cos(rads);
double[][] transform = new double[3][3];
int panelW = this.getWidth();
int panelH = this.getHeight();
transform[0][0] = cos;
transform[0][1] = -sin;
transform[1][0] = sin;
transform[1][1] = cos;
double[] transformedX = new double[xCord.length];
double[] transformedY = new double[yCord.length];
int[] updatedX = new int[xCord.length];
int[] updatedY = new int[yCord.length];
for(int i = 0;i<updatedX.length;i++) {
updatedX[i] = xCord[i];
updatedY[i] = yCord[i];
transformedX[i] = Math.round(updatedX[i] * transform[0][0] + updatedY[i] * transform[0][1] + transform[0][2]);
transformedY[i] = Math.round( updatedX[i] * transform[1][0] + updatedY[i] * transform[1][1] + transform[1][2]);
updatedX[i] = (int)transformedX[i];
updatedY[i] = (int)transformedY[i];
}
g.setColor(Color.orange);
g.fillRect(0, 0, panelW, panelH);
g.setColor(Color.black);
g.drawPolygon(updatedX, updatedY, updatedX.length);
}
}
The main problem is in "RotateShape" method.I just can't figure out,how to make it work right.

Your rotation code is correct. But you are trying to transform more points than there are in the polygon. The internal xpoints and ypoints arrays are not necessarily filled completely. Replace all occurences of xCord.length and yCord.length with poly.npoints and you are good to go.

Related

How to add multiple rectangles to a jframe(trying to code 2048 in an easy way)

I made the game already and wanted to make my GUI look better with rectangles not with jlabels and now I´ve come to realize that only the last rectangle that is drawn is shown on the GUI
I already tried it with different layouts
my GUI class:
public class GUI_N
{
private Spiel spiel;
private KeyEvent e;
private String beste;
private int beste1;
private DrawingComponent[][] feld;
GUI_N(){
feld = new DrawingComponent[4][4];
spiel = new Spiel();
beste1 = 0;
beste = "Highscore: "+beste1;
JFrame g=new JFrame("2048 - Main");
g.setSize(500,500);
g.setFocusable(true); //wichtig für KeyListener
g.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
int i = 0;
int j = 0;
int h = 0;
int l = 0;
while(i<4)
{
while(j<4)
{
if(i==0){
h = 50;
}else if(i==1){
h = 100;
}else if(i==2){
h = 150;
}else if(i==3){
h = 200;
}
if(j==0){
l = 50;
}else if(j==1){
l = 100;
}else if(j==2){
l = 150;
}else if(j==3){
l = 200;
}
feld[i][j] = new DrawingComponent(l,h,50,50);
feld[i][j].setBounds(l,h,50,50);
j++;
}
j=0;
i++;
}
i = 0;
j = 0;
while(i<4)
{
while(j<4)
{
g.add(feld[i][j]);
j++;
}
j=0;
i++;
}
//g.getContentPane().setBackground(new Color(20, 40, 50));
g.setVisible(true);
}
public static void main(String[] args) {
new GUI_N();
}
}
my rectangle class:
public class DrawingComponent extends JComponent
{
private Graphics2D g2;
private int wert;
private int x;
private int y;
private int w;
private int h;
public DrawingComponent(int px,int py,int pw,int ph)
{
x=px;
y=py;
w=pw;
h=ph;
}
public void paintComponent(Graphics g)
{
g2 = (Graphics2D) g;
Rectangle rect1 = new Rectangle(x,y,w,h);
g2.setColor(Color.RED);
g2.fill(rect1);
}
public void setWert(int x)
{
wert = x;
}
public int getWert()
{
return wert;
}
}
as I said only the last drawn rectangle is shown.
How do I achieve this?
Right now you're adding the rectangles directly to your frame. You should have a JPanel layer in between, to which you can give a LayoutManager (GridLayout would be a good one to look at) to arrange all your rectangles.
So you would have something like this:
JFrame g = new JFrame("2048 - Main");
// GridLayout (on next line) takes number of rows and columns
JPanel panel = new JPanel(new GridLayout(4, 4));
// ... add all the rectangles to the panel here
g.add(panel);
And then you would add your rectangles to the panel, not the frame. As you add them, they will automatically go into place in the grid.
panel.add(feld[i][j]);
Also, if you use GridLayout, it will resize and fit the components to the grid dynamically, so it may save you some code as well, since you wouldn't need to hardcode their sizes in the GUI class.

Double dimensional array with colours doesn't paint in paintComponent

I've been working on a dots look-a-like, but I'm having trouble painting the dots on the board. The array seems to work but it doesn't want to paint it.
Sorry, some of my variables are in Dutch but that shouldn't really pose too many confusion.
public class Bord extends JFrame{
Slang slang = new Slang();
Tile[][] tile = new Tile[6][6];
private JPanel menuPanel;
private JPanel gridPanel;
private JLabel levelTitel;
private JLabel levelNummer;
private JLabel scoreTitel;
private JLabel scoreNummer;
private JLabel targetTitel;
private JLabel targetNummer;
private JLabel timeTitel;
private JLabel timeNummer;
private JLabel pauzeKnop;
public Bord() {
super("Dots");
//setLocationRelativeTo(this);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
maakAttributen();
maakListeners();
maakLayout();
pack();
setSize(650, 750);
setVisible(true);
getContentPane();
repaint();
//TODO automatic size
}
public void maakAttributen() {
levelTitel = new JLabel("level");
levelNummer = new JLabel("1");
scoreTitel = new JLabel("score");
scoreNummer = new JLabel("2");
targetTitel = new JLabel("target");
targetNummer = new JLabel("3");
timeTitel = new JLabel("time");
timeNummer = new JLabel("4");
//TODO image in knop zetten
pauzeKnop = new JLabel("PAUZE");
}
public void maakListeners() {
}
public void maakLayout() {
JPanel menuPanel = new JPanel(new GridLayout(0, 5, 5, 5));
JPanel gridPanel = new JPanel(new GridLayout(0, 7, 5, 5));
add(menuPanel, BorderLayout.PAGE_START);
add(gridPanel, BorderLayout.CENTER);
//menu attributen aan menu toevoegen
menuPanel.add(levelTitel);
menuPanel.add(scoreTitel);
menuPanel.add(targetTitel);
menuPanel.add(timeTitel);
menuPanel.add(pauzeKnop);
menuPanel.add(levelNummer);
menuPanel.add(scoreNummer);
menuPanel.add(targetNummer);
menuPanel.add(timeNummer);
//grid met dots toevoegen
for (int x = 0; x < 6; x++) {
for (int y = 0; y < 6; y++) {
RandomKleur kleur = new RandomKleur();
tile[x][y] = new Tile(kleur.getKleur());
gridPanel.add(new myDots());
}
}
}
private class myDots extends JPanel {
#Override
protected void paintComponent(Graphics g) {
int h = getHeight();
int w = getWidth();
super.paintComponent(g);
for (int x = 0; x < 6; x++) {
for (int y =0; y < 6; y++) {
g.setColor(tile[x][y].getKleur());
g.fillOval(h / 2, w / 2, 33, 33);
}
}
}
}
}
I've tried debugging it and it gives some kind of null pointer exception sometimes.
You basic painting logic is wrong. You are adding 36 Dot panels to the frame, but then in the painting logic you are repainting all 36 dots on top of one another so only the last dot painted will display. The paintComponent() method should only be painting a single dot.
You need to change your MyDots class to accept a Tile as a parameter and then save the Tile object as an instance variable of the class. Then the code would be something like:
for (int x = 0; x < 6; x++) {
for (int y = 0; y < 6; y++) {
RandomKleur kleur = new RandomKleur();
tile[x][y] = new Tile(kleur.getKleur());
//gridPanel.add(new myDots());
gridPanel.add(new myDots(tile[x][y]));
}
}
I don't know if you even need the tile array, because now the MyDots class has the tile information.
Then Your painting logic should be something like:
//for (int x = 0; x < 6; x++) {
//for (int y =0; y < 6; y++) {
//g.setColor(tile[x][y].getKleur());
g.setColor(tile.getKleur()); // where "tile" is the instance variable
g.fillOval(h / 2, w / 2, 33, 33);
//}
//}
Who knows why you get the NPE, because the exception is not related to the code you posted.
By the way class name should start with an upper case character. It should be "MyDot".
Edit:
Do I have to create a new method in MyDots?
You need to create a constructor for your class:
public class MyDots
{
private Tile tile;
public MyDots(Tile tile)
{
this.tile = tile;
}
#Override
protectect paintComponent(Graphics g)
...
}

Transferring JFrame to JPanel

I created a simple "elevator" program (it's still in the beginning stages) that goes up 1 floor when I click UP and vice versa.
I messed up pretty badly when I drew all my components into JFrame, and as expected, it flickers every time I click the button (repaints). I know the solution to be draw in the JPanel and put the said panel in the JFrame, but I have a problem translating my JFrame components into JPanel. I've tried extending JPanel, creating a JFrame object and then overriding the paintComponent() method and doing my drawing there, but when I compile it does not draw it at all. It only creates the frame.
Can anyone help me or give me tips on how to proceed "transferring" my programming from JFrame based to JPanel based? Thank you in advance!
My code is below:
import java.awt.*;
import javax.swing.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.Timer;
import java.math.*;
public class MyCanvas extends JFrame {
private int up = 0;
private int down = 0;
private int movefloorup = 0;
private int buildingType;//type of building (1 = Residential, 2 = Commercial)
private int totnumoffloors; //for the total number of floors
private int numofelevators; //for the number of elevators to be generated
private int floorlimit = 0; //to determine up until where the elevator will be moving
private int currenttime; //determine the time of the day the elevator is operating (1 = Morning, 2 = Lunch, 3 = Afternooon)
//For elevator resetting to bottom
private int rectX = 190;
private int switchmarker = 0;
//Lines and stuff
private int horizborder = 0;
private int bordercount = 0;
private class UpAction implements ActionListener //move the elevator up
{
public void actionPerformed(ActionEvent e)
{
if(movefloorup<780){
repaint();
up++;
movefloorup = movefloorup + 130;
//repaint();
}
else
{
switchmarker = 1;
movefloorup = 0;
repaint();
}
}
}
private class DownAction implements ActionListener //move the elevator down
{
public void actionPerformed(ActionEvent e)
{
if(movefloorup>0){
repaint();
down++;
movefloorup = movefloorup - 130;
//repaint();
}
else
{
switchmarker = 0;
movefloorup = 780;
repaint();
}
}
}
public MyCanvas(int buildingType, int totnumoffloors, int numofelevators, int currenttime){
this.buildingType = buildingType;
this.totnumoffloors = totnumoffloors;
this.numofelevators = numofelevators;
this.currenttime = currenttime;
String title;
if(this.buildingType == 1)
{
title = "Residential Building";
}
else
{
title = "Commercial Building";
}
setLayout(null);
horizborder = 500*((int)Math.ceil((double)totnumoffloors/7)); //calculating how wide the window should be
bordercount = ((int)Math.ceil((double)totnumoffloors/7)); //counts how many borders there will be
//NOTES
//A floor is 130 units in the Y-Direction
//Drawing the bulding layout
if(totnumoffloors>7)
{
setSize(horizborder, 1000);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle(title);
setLayout(new BorderLayout());
getContentPane().setBackground(Color.WHITE);
}
else{
setSize(500, 1000); //suitable for 7 floors
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle(title);
setLayout(new BorderLayout());
getContentPane().setBackground(Color.WHITE);
}
JButton upButton = new JButton("UP");
upButton.addActionListener(new UpAction());
add(upButton, BorderLayout.NORTH);
JButton downButton = new JButton("DOWN");
//downButton.setBounds(0, 0, 220, 30);
//downButton.setLocation(100, 100);
downButton.addActionListener(new DownAction());
add(downButton, BorderLayout.SOUTH);
}
public void paint(Graphics graphics){ //this is where you draw shit
super.paint(graphics);
//Floors
graphics.setColor(Color.RED);
int numoffloorsY = 830;
int numoffloorsX = 830;
int floorbeginning = 0;
int floorcounter = 1;
int floorflag = 0;
int rightedge = 500;
if(this.totnumoffloors>7) //drawing the floors
{
//Default number of floors -> 7
for(int i = 0;i<totnumoffloors;i++)
{
graphics.setColor(Color.RED);
graphics.drawLine(floorbeginning,numoffloorsX,rightedge,numoffloorsY); //FLOORS
graphics.setColor(Color.DARK_GRAY);
graphics.setFont(new Font("TimesRoman", Font.PLAIN, 15));
graphics.drawString(" "+floorcounter, floorbeginning+10, numoffloorsY+20); //SAVE THIS FOR DRAWING FLOORS
numoffloorsY = numoffloorsY - 130;
numoffloorsX = numoffloorsX - 130;
floorcounter++;
floorflag++;
if(floorflag==7)
{
floorbeginning = floorbeginning + 500;
rightedge = rightedge+500;
numoffloorsY = 830;
numoffloorsX = 830;
floorflag = 0;
}
}
//Every other floor past 7 will be added here.
/*for(int i = 0;i<totnumoffloors-7;i++)
{
//System.out.println("LOLOOLO");
graphics.setColor(Color.RED);
graphics.drawLine(floorbeginning,numoffloorsX,horizborder,numoffloorsY);
graphics.setColor(Color.DARK_GRAY);
graphics.setFont(new Font("TimesRoman", Font.PLAIN, 15));
graphics.drawString(" "+floorcounter, floorbeginning, numoffloorsY+20);
//graphics.setColor(Color.DARK_GRAY);
//graphics.drawLine(500,0,500,1000);
floorcounter++;
numoffloorsY = numoffloorsY - 130;
numoffloorsX = numoffloorsX - 130;
}*/
//DIVIDING LINE -> to determine the first 7 floors from the ones higher up.
for(int i=0;i<bordercount;i++)
{
graphics.setColor(Color.DARK_GRAY);
graphics.drawLine(500*i,0,500*i,1000);
}
}
else{
for(int i = 0;i<this.totnumoffloors;i++)
{
graphics.setColor(Color.RED);
graphics.drawLine(0,numoffloorsX,500,numoffloorsY);
graphics.setColor(Color.DARK_GRAY);
graphics.setFont(new Font("TimesRoman", Font.PLAIN, 15));
graphics.drawString(" "+floorcounter, floorbeginning+10, numoffloorsY+20); //SAVE THIS FOR DRAWING FLOOR
numoffloorsY = numoffloorsY - 130;
numoffloorsX = numoffloorsX - 130;
floorcounter++;
}
}
//Drawing the elevators
if(up>0 && movefloorup<1000){
graphics.setColor(Color.GRAY);
if(switchmarker==1)
{
System.out.println("ELSA");
rectX = 690;
//rectX = rectX + 190;
}
else
{
rectX = 190;
}
System.out.println(rectX);
graphics.fillRect(rectX, 850-movefloorup, 100, 100); //this needs to match the stats of the rectangle to fill it properly
graphics.drawRect(rectX, 850-movefloorup, 100, 100);
//Line for the door
graphics.setColor(Color.BLACK);
graphics.drawLine(rectX+50, 850-movefloorup, rectX+50, 950-movefloorup); //match the y-coordinate for the rectangle, add 100 for the y-coordinate of the other end
System.out.println(movefloorup);
System.out.println(switchmarker);
//drawLine(x1, y1, x2, y2); --From (x1,y1) to (x2,y2)
}
else if(down>0 && movefloorup>0)
{
graphics.setColor(Color.GRAY);
if(switchmarker==1) //This determines when the elevator should move to the next column of higher floors.
{
System.out.println("ELSA");
rectX = 500;
}
System.out.println(rectX);
graphics.fillRect(rectX, 850-movefloorup, 100, 100); //this needs to match the stats of the rectangle to fill it properly
//graphics.drawRect(190, 850 + movefloorup, 100, 100); //FIRST FLOOR
graphics.drawRect(rectX, 850-movefloorup, 100, 100); //SECOND FLOOR (135 units difference in Y-axis between floors)
//x-coordinate, y-coordinate, width, height
//Line for the door
graphics.setColor(Color.BLACK);
graphics.drawLine(rectX+50, 850-movefloorup, rectX+50, 950-movefloorup); //match the y-coordinate for the rectangle, add 100 for the y-coordinate of the other end
System.out.println(movefloorup);
System.out.println(switchmarker);
}
else
{
graphics.setColor(Color.GRAY);
graphics.fillRect(190, 850, 100, 100); //this needs to match the stats of the rectangle to fill it properly
graphics.drawRect(190, 850, 100, 100); //FIRST FLOOR
graphics.drawRect(190, 850, 100, 100); //SECOND FLOOR (135 units difference in Y-axis between floors)
//x-coordinate, y-coordinate, width, height
//Line for the door
graphics.setColor(Color.BLACK);
graphics.drawLine(240, 850, 240, 950); //match the y-coordinate for the rectangle, add 100 for the y-coordinate of the other end
//System.out.println("In else!");
}
}
}
The main class just gets input from the user, such as the number of floors, time of day, etc.
This is going to be a little messy.
Start by creating a custom component that extends from JPanel (I'll call it ElevatorPane).
Take the contents of the current paint method and place them within this components paintComponent method. This will involve moving the instance variables that the paintComponent method will need including, totnumoffloors, bordercount, up, down, movefloorup, switchmarker, rectX
This is where it gets a little messy...
You need to take the contents of your ActionListeners and translate these into methods within the ElevatorPane, this way you expose the functionality without exposing the details...
Create a constructor within ElevatorPane that takes the number of floors.
Override the getPrefferedSize method of ElevatorPane and return the size that the component needs to be to satisfy your needs...
Create an instance field of ElevatorPane in MyCanvas, instantiate it and add it to the frame.
Clean, build, run...

AffineTransform seeming to ignore component bounds

I have the following:
public class ParametricEQView extends JPanel implements PluginView {
private static final int BAND_WIDTH = 3;
private static final int THROW_HEIGHT = 64;
private static final int WIDTH = 128*BAND_WIDTH + 2*MARGIN;
private static final int HEIGHT = 2*THROW_HEIGHT + 2*MARGIN;
private static final int MID_HEIGHT = THROW_HEIGHT + MARGIN;
private final ParametricEQ _peq;
public ParametricEQView(ParametricEQ peq) {
super();
_peq = peq;
SwingUtils.freezeSize(this, WIDTH, HEIGHT);
setToolTipText("Parametric Equalizer");
}
#Override
public void paint(Graphics g) {
final Graphics2D g2d = (Graphics2D) g;
final int max = findMax();
g.setColor(BACKGROUND);
g.fillRect(0, 0, WIDTH, HEIGHT);
g.setColor(DATA);
final double scalingFactor = -((double) THROW_HEIGHT) / max;
final double[] fineLevels = _peq.getFineLevels();
int x = MARGIN;
int h;
final int[] xPoints = new int[128];
final int[] yPoints = new int[128];
for (int i = 0; i < 128; ++i) {
h = (int) (fineLevels[i] * scalingFactor);
xPoints[i] = x;
yPoints[i] = MID_HEIGHT + h;
x += BAND_WIDTH;
}
g.drawPolyline(xPoints, yPoints, 128);
g.setColor(AXES);
g.drawLine(MARGIN, MARGIN, MARGIN, HEIGHT-MARGIN);
g.drawLine(MARGIN, MID_HEIGHT, WIDTH-MARGIN, MID_HEIGHT);
g.setFont(AXIS_FONT);
final FontMetrics metrics = g.getFontMetrics();
int width = (int) metrics.getStringBounds(AXIS_LABEL_INPUT_MIDINUM, g).getWidth();
g.drawString(AXIS_LABEL_INPUT_MIDINUM, WIDTH-MARGIN-width, HEIGHT-3);
final AffineTransform atx = new AffineTransform();
atx.setToRotation(-Math.PI/2, 0, HEIGHT);
g2d.setTransform(atx);
final String topLabel = "+" + max;
width = (int) metrics.getStringBounds(topLabel, g).getWidth();
g2d.drawString(topLabel, HEIGHT-MARGIN-width, HEIGHT+10);
width = (int) metrics.getStringBounds(AXIS_LABEL_OUTPUT_VELOCITY, g).getWidth();
g2d.drawString(AXIS_LABEL_OUTPUT_VELOCITY, MID_HEIGHT-(width/2), HEIGHT+10);
g2d.drawString("-" + max, MARGIN, HEIGHT+10);
}
private int findMax() {
int max = 3;
for (int i = 0; i < 128; ++i)
max = Math.max(max, (int) Math.ceil(Math.abs(_peq.getFineLevels()[i])));
return max;
}
}
This is what it looks like:
The ParametricEQView is the component with the white background filling most of the window. In this image its coordinates are (0,0) in the containing frame and everything is great. However, if I resize the window so that the ParametricEQView moves over a bit (it has a fixed size and is set to be centered in its available space), the rotated text stays relative to the (0,0) of the frame instead of the component:
Everything else draws relative to the panel, it's just the rotated text that doesn't. What am I doing wrong?
When you call g2d.setTransform(atx); you override the transform currently set in the Graphics object, i.e. the translation between the panel and its parent frame. That's why the text is drawn in the frame referential, and not in the panel referential.
The correct code would be to get the current transform and modify it or directly call Graphics2D.rotate(double).
1) For custom paintings you need to override protected void paintComponent(Graphics g) instead of public void paint(Graphics g). Read more about customPaintings.
2)Seems you have your problem, because you do something like next for creation of GUI:
JFrame frame = new JFrame();
JPanel p = new JPanel();
ParametricEQView view = new ParametricEQView();
view.setPreferredSize(new Dimension(200,200));
p.add(view);
frame.add(p);
in that case ParametricEQView doesn't resize as you want, because JPanel use FlowLayout as default.
You need to use another LayoutManager for your panel, for example BorderLayout.
Try something like next:
JFrame frame = new JFrame();
ParametricEQView view = new ParametricEQView();
frame.add(view);
or
JPanel panel = new JPanel(new BorderLayout());
panel.add(view,BorderLayout.CENTER);
frame.add(panel);
in that case your ParametricEQView panel will be painting in proper way.

display JLabels dynamically in JPanel/JFrame

I am trying display images in sequential manner, but having difficulties in displaying(only last image is getting displayed on screen). I tried using CardLayout but as my number of JLabels(which contains ImageIcon) are high so it's giving me outofmemory exception. here's my code:
I have JFrame inside that I have JPanel in which I am trying to display JLabel one by one.
public class ImageMain extends JFrame implements ActionListener{
private static final long serialVersionUID = 2916361361443483318L;
private JFileChooser fc = null;
private JMenuItem item1,item2;
private BufferedImage image = null;
private JPanel panel = null;
private int width = 0;
private int height = 0;
private BorderLayout card;
private Container contentPane;
public ImageMain() {
JFrame frame = new JFrame("Image Extraction Tool");
frame.setExtendedState(Frame.MAXIMIZED_BOTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
contentPane = frame.getContentPane();
panel = new JPanel();
card = new BorderLayout();
panel.setLayout(card);
panel.setBackground(Color.white);
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("Menu");
menuBar.add(menu);
item1 = new JMenuItem("Browse an image");
item2 = new JMenuItem("Exit");
item1.addActionListener(this);
item2.addActionListener(this);
menu.add(item1);
menu.add(item2);
frame.setJMenuBar(menuBar);
contentPane.add(panel);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
ImageMain img = new ImageMain();
}
});
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == item1){
if(fc == null)
fc = new JFileChooser();
int retVal = fc.showOpenDialog(null);
if(retVal == JFileChooser.APPROVE_OPTION){
File file = fc.getSelectedFile();
try {
image = ImageIO.read(file);
height = image.getHeight();
width = image.getWidth();
int[][] pixelData = new int[height * width][3];
int[] rgb;
int counter = 0;
for(int i = 0; i < height; i++){
for(int j = 0; j < width; j++){
rgb = getPixelData(image, i, j);
for(int k = 0; k < rgb.length; k++){
pixelData[counter][k] = rgb[k];
}
counter++;
}
}
for(int m=pixelData.length-10; m < pixelData.length; m++){
System.out.println(m);
int[] pix = new int[width*height*3];
for(int i=0;i< width*height*3; i+=3){
pix[i] = pixelData[m][0];
pix[i+1] = pixelData[m][1];
pix[i+2] = pixelData[m][2];
}
JLabel createImageLabel = createImageLabel(pix);
panel.add(createImageLabel);
// panel.revalidate();panel.repaint();
contentPane.revalidate();contentPane.repaint();
Thread.sleep(2000);
}
} catch (IOException e1) {
System.out.println("IO::"+e1.getMessage());
}catch(Exception e1){
System.out.println("Exception::"+e1.getMessage());
}
}
}
if(e.getSource() == item2){
System.exit(0);
}
}
private int[] getPixelData(BufferedImage image, int x, int y) {
int argb = image.getRGB(y, x);
int rgb[] = new int[] {
(argb & 0x00ff0000) >> 16 , //red
(argb & 0x0000ff00) >> 8, //green
argb & 0x000000ff //blue
};
return rgb;
}
private JLabel createImageLabel(int[] pixels){
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
WritableRaster raster = image.getRaster();
raster.setPixels(0, 0, width, height, pixels);
JLabel label = new JLabel(new ImageIcon(image));
return label;
}
}
please advice.
Thanks in advance.
Please check for similar questions and answers on this site about not calling Thread.sleep(...) inside of the Swing event thread. As they state, calling this will put your entire Swing GUI to sleep which is not your intention, I'm sure. Since your problem is no different from all the rest, the solution is the same as well: use a Swing Timer for intermittent actions, and use a background thread such as that generated by a SwingWorker for long-running background actions -- such as reading in images.
Also, if all you're doing is swapping images, then one JLabel should work fine. Just swap the ImageIcon that it displays in your Swing Timer.
Edit
You state:
I am not sure how to iterate my 2D array with swing Timer, every 2 sec I want to iterate my array and perform some action.
Suggestions:
Give your timer a delay of 2000 (for milliseconds)
Give the Timer's ActionListener one or two int counter fields that are initialized to 0.
In the actionPerformed method, use the counter to get the item of interest, and then advance the counter(s).
Read the Swing Timer Tutorial.

Categories

Resources