I am having an issue getting this code to run properly. It compiles and initially the frame displays properly. The problem is that when I manually re-size the frame by either maximizing or by dragging the side of the frame over, the text disappears. I am using jGRASP, not sure if that is the issue or not. The code seems to make sense to me, and like I said, it compiles(I know that does not necessarily make it right). I'm still a newbie at this so if anyone can point me in the right direction I would be very appreciative.
import javax.swing.*;
import java.awt.*;
public class JFontSizes extends JFrame {
int x = 5;
int y = 50;
String homework = "This is the first homework assignment";
public JFontSizes() {
super("Increasing Font Sizes");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void paint(Graphics brush) {
super.paint(brush);
// This works sometimes. I am not sure if it is a jGRASP issue or something else.
// If I resize the frame, the text disappears, and I cannot get the text to start at the top of the frame
for(int n = 6; n<= 20; ++n) {
brush.setFont(new Font("Serif", Font.PLAIN, n));
brush.drawString(homework, x, y);
y += 15;
}
}
public static void main(String[] args) {
JFontSizes frame = new JFontSizes();
frame.setSize(400, 500);
frame.setVisible(true);
}
}
When first time paint() is called the value of y was 5. And it is incremented in a loop. So that before leaving paint() its value will be 275.
But when you resize your frame paint() is called again and this time the value of y is 275 and when brush.drawString(homework, x, y); is called the homework is printed at 275px bottom from top left corner.
So what you need to do is re-initialize y every time :
public void paint(Graphics brush) {
y = 50;
....
Edit :
As commented by camickr you should override paintComponent(...) instead of paint(...) until you have some specific reason to override paint().
And you mean you are not able to print text at top (even in beginning) then it is because you had initialized y with 50. Which means the text will be drawn at 50px from top.
Related
When I run the program I'm facing some problem with JFrame Buffer, I don't know what the problem exactly is. When I run the program, it displays some dialog box part on the top left corner of the buffer.
Here is output of my program:
And following is the code
Thank you.
import java.awt.*;
import java.util.*;
import javax.swing.*;
public class Main extends JPanel
{
public void paintComponent(Graphics g)
{
super.paintComponent(g);
int[] x1 = new int[10];
int[] y1 = new int[10];
int i,n;
Polygon p=new Polygon();
n = Integer.parseInt(JOptionPane.showInputDialog("Enter no. of co-ordinates of polygon: "));
System.out.println(" no. of co-ordinates of polygon are :"+n);
for(i=0;i<n;i++)
{
x1[i] = Integer.parseInt(JOptionPane.showInputDialog("Enter x co-ordinates of polygon: "));
y1[i] = Integer.parseInt(JOptionPane.showInputDialog("Enter y co-ordinates of polygon: "));
}
for(i=0;i<n-1;i++)
{
g.drawLine(x1[i],y1[i],x1[i+1],y1[i+1]);
}
g.drawLine(x1[n-1],y1[n-1],x1[0],y1[0]);
}
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setTitle("Polygon");
frame.setSize(500,500);
Container contentPane = frame.getContentPane();
contentPane.add(new Main());
frame.setVisible(true);
}
}
Never display an JOptionPane from a painting method. Painting methods are for painting only, they are not for getting user input.
Instead you need to do the following:
The JOptionPane should be displayed from the main method to gather the x/y parameters.
Modify your Main() class to have a method like addPoint(int x, int y).
The above method will then save the x/y values to an ArrayList object in your class. I would store Point objects in this list.
The painting method will then iterate through the List and then paint each line.
The paintComponent( ... ) method is called whenever 'something' (the AWT EDT thread) thinks the component needs to be repainted. That method is called often and often at moments you didn't expect it to be called. So, don't show a JOptionPane in the body of that method.
So it is better to call from main method only as camickr said.
Good day,
I might've been a bit vague with the title of my question, but I hope this will explain. The scenario is quite basic - I have a JFrame, in which I have an array of JPlanes. The idea is that when I click on one of them, upon clicking in should become black. Here is the code:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.*;
import javax.swing.border.Border;
public class PixelArt {
JFrame frame;
Border blackline;
JPanel squares[][] = new JPanel[100][100];
int x;
int y;
public PixelArt() {
frame = new JFrame("Pixel Art");
frame.setSize(1000, 1000);
frame.setLayout(new GridLayout(100, 100));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
for (int i = 0; i < 100; i++) {
for (int j = 0; j < 100; j++) {
x = i;
y = j;
squares[i][j] = new JPanel();
squares[i][j].setBorder(BorderFactory.createDashedBorder(null));
squares[i][j].addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
x = e.getX();
y = e.getY();
squares[x][y].setBackground(Color.black);
}
});
frame.add(squares[i][j]);
}
}
frame.setVisible(true);
}
public static void main(String[] args) {
new PixelArt();
}
}
The actual problem is that this code does not do what I explained above. It does color in one of the JPlane's black when clicked, but within a 9x9 area starting from the upper corner of the grid. I do not have an explanation for this. The problem seems to be in the following 2 lines:
x = e.getX();
y = e.getY();
One of my guesses is that I have some kind of an offset in the coordinate system, but then this does not explain why regardless on which JPanel I press, the JPanels colored are only in the upper 9x9 area.
Does anyone have a clue how I could fix the problem I described above? If something is unclear in my explanation, please ask. Thank you in advance.
Here is a screenshot of the working code:
you can detect clicked panel using event.getSource() like follow example code
public void mouseClicked(MouseEvent e) {
JPanel panel = (JPanel)e.getSource();//
panel.setBackground(Color.black);
}
the problem is you can't use x,y directly as indexes to array element. because panels has a width and borders too.if you go with x y you have to make some mathematics logic. for example you click middle of your first jpanel in the grid so let's assume x and y coordinate is about 10px but in your code you call [10][10] Janel but actually you should call [0][0].
also as #Cr0w3 says you add listners to all panels.so if you clicked middle of first grid cell or last grid cell there is no difference in x,y.
but if you make a mathematical logic to detect clicked element you need to take in to account your frame/main panel width(also have to update when risize) and border thickness.
also do you really want to do this using 10000 panels ? you may need use a one panel and override paint component method.10000 panels isn't effective for this kind of thing.if you resize or click quickly on panels you will see it take a lot of time. so you may need to draw graphics on a jpanel .see this example
I think you should not add the listener to the panels themselves, but to the frame.
Because the X and Y coordinates might be relative to the panel size (e.g., upper corner of the panel returns 1/1, thus you apply the color to the panel at [1][1] even though you click the panel at [50][50].
If you use the frame for listening at the point you will receive 50/50 as coordinates.
Unfortunately I cannot comment, because of my low reputation but I hope I could help a little.
If you want to add a listener to the panel do not use the coordinates and just apply color to the clicked panel without listening to the coordinates. Using e.getSource() should help you in that case.
I got a bit of a problem which I am completely baffled about. Not even sure where to start to debug the problem.
I have a JFrame which promotes the user to enter a number, lets say the number was 4. I sent this number to my paint component to create a vertical line of 4 x 50. SO the line should be 200 in length. Which it does.
But if I minimise and reopen the window, that 4 seems to be multiplied again by 50 giving 200. Then that again is multiplied by 50 making the line 10,000.
I placed my paint component code in hope that it would help as the issue must be there, but if more code is needed I'll be happy to post.
class mainPanel extends JPanel
{
int processes;
public mainPanel(int x) //the value x is passed from another class, this was the number the user chooses...i.e 4
{
processes = x;
setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY, 5));
}
public Dimension getPreferredSize() {
return new Dimension (1000, 1000);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
int storedProcesses = processes;
// Draw Title
g.setFont(new Font("TimesRoman", Font.PLAIN, 28));
g.drawString("We place the title here",380,50);
processes = processes * 50;
g.drawLine(100,100,100, processes+100); //Vertical (down) line
//labels for vertical line
g.setFont(new Font("TimesRoman", Font.PLAIN, 20));
int y = 125;
for (int i=1; i<=storedProcesses; i++) //this loop keeps repeating and getting larger for some unknown reason...then its repainting my JFrame
{
g.drawString(String.valueOf(i), 70,y);
y=y+50;
System.out.println("Loop" + storedProcesses); //used for debugging
}
g.drawLine(100,processes+100,1000,processes+100); //Horizontal (across) line
}
}
I've attached some screen shots to illustrate what's going on with 1 process as an example.
Before I minimise the window (this is fine):
This is after I minimise and re maximise the window
You can't control when Swing invokes the paintComponent() method. Therefore you should NEVER change a property of your class in the paintComponent() method. All variables that you manipulate in the paintComponent() method should be local variables.
processes = processes * 50;
Your current code is modifying the "processes" variable. Don't do this.
Is there anything obvious wrong with this line of code? I want rectangle to stay centered regardless the size of the window. But this donĀ“t work for some reason, the rectangle stays the same place.
public void run() {
setSize(800, 800);
createEntireFigure();
}
private void createEntireFigure(){
int centerOfWindowWidth = getWidth() / 2;
int centerOfWindowHeight = getHeight() / 2;
GRectWithGLabel ("A String",centerOfWindowWidth, centerOfWindowHeight);
}
Your rectangle size code is only called on rectangle creation, and so it makes sense that the rectangle's position will not change if the GUI is re-sized. You need to somehow listen for size changes in your GUI and call code to re-position the rectangle then for this to work. What graphics library are you using?
My code plots 5000 points of time series data in a panel that is 581 pixels wide by default, but this width changes when the user resizes the window. My code also plots several rectangular markers that each identify a local maximum/peak in this same space.
I need to enable the user to right click on any of the rectangular-peak-markers so that the user can manually delete any false peak. The problem is that my code is reporting different x-coordinates than expected when the user right-clicks on a peak-marker. I suspect that the reason may have to do with rounding error in converting from 581 x-pixels back to 5000 data indices. But I am not certain of the reason.
Can anyone suggest a solution that enables my users to manually select one of the above-described peak markers by right-clicking on it?
I am enclosing relevant sections of the code below. My actual code is very, very long, and too complicated to post. But the relevant portions below should be enough for someone to see the logic of my approach, and to then suggest a more effective approach.
The code that declares the class in question is:
class SineDraw extends JPanel implements MouseMotionListener, MouseListener {
// lots of code, including the two segments excerpted below
}
This segment of code overloads the paintComponent of the JPanel so that my data is plotted:
// declare some variables
ArrayList<Double> PeakList = new ArrayList<Double>() // this ArrayList is populated by an extraneous process
visiblePoints = 5000
hstep = getWidth()/visiblePoints //=581/5000 by default, but will change when user resizes window
int numPeaks = PeakList.size();
// scale (y-coordinate) data relative to height of panel
pts = new double[visiblePoints]
for (int i = 0; i < pts.length-1; i++){pts[i]=//data vertical scaled to fill panel;}
// plot the 5000 time-series-data-points within the 581 pixels in x-axis
for (int i = 1; i < visiblePoints; i++) {
int x1 = (int) ((i - 1) * hstep);
int x2 = (int) (i * hstep);
int y1 = (int)pts[i - 1];
int y2 = (int)pts[i];
g2.drawLine(x1, y1, x2, y2);
}
// plot a rectangle for each of the local peaks
for(int m=0;m<=(numPeaks-1);m++){
if(i==(int)(PeakList.get(m)){
int currentVal = (int)pts[(int)(PeakList.get(m)];
g2.drawRect((int)(PeakList.get(m), currentVal, 6, 6);
}
}
This section of code is for handling the right-clicking of the mouse:
public void mousePressed(MouseEvent e){
// check to see if right mouse button was clicked
boolean jones = (e.getModifiers()&InputEvent.BUTTON3_MASK)==InputEvent.BUTTON3_MASK;
if(jones==true){
// test the value returned as x-coordinate when user right-clicks (code always underestimates x-coordinate of local peaks by this test)
double ReverseHstep = visiblePoints/getWidth();
int getX_ConvertedTo_i = (int) (e.getX()*ReverseHstep);
System.out.println("getX_ConvertedTo_i is: "+getX_ConvertedTo_i );
// check to see if peaklist contains a value within the x-coordinates of the user-selected-rectangle
if(PeakList.contains((double)(e.getX()-3))
||PeakList.contains((double)(e.getX()-2))
||PeakList.contains((double)(e.getX()-1))
||PeakList.contains((double)(e.getX()))
||PeakList.contains((double)(e.getX()+1))
||PeakList.contains((double)(e.getX()+2))
||PeakList.contains((double)(e.getX()+3))
){
// handling code will go here, but for now it is a print test that never succeeds because x-coordinate is always underestimated
System.out.println("You just selected a peak!");
}
}
repaint();
}
I suggest you create objects (in this case Rectangles) for each thing you want to be clickable. Here is an over-simplified example of how you can make something you draw clickable. The key thing to take away from this is the mouseClicked method which will display a dialog only if the mouse clicked within the rectangle.
One tricky point is that I wasn't able to figure out how to make the rectangle filled in with color without drawing another rectangle over it. I'll leave that one for you ;-)
public class Canvas extends JPanel implements MouseListener{
private Rectangle rect = new Rectangle(100,100);
public Canvas(){
this.addMouseListener(this);
rect.setSize(100, 100);
}
#Override
public void paintComponent(Graphics g){
g.setClip(rect);
g.setColor(Color.RED);
g.fillRect(0, 0, 100, 100);
}
#Override
public void mouseClicked(MouseEvent e){
if(rect.contains(e.getPoint())){
JOptionPane.showConfirmDialog(this, "Click!");
}
}
// The rest of the MouseListener methods have been cut out
public static void main(String[] a){
JFrame frame = new JFrame("Canvas Thingy");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(0, 0, 300, 300);
frame.add(new Canvas());
frame.setVisible(true);
}
}