I want to develop a Java Applet which shows visualization of Sorting. So I have written code like this...
public class SortNumbersGUI extends JApplet {
private static final long serialVersionUID = 1L;
List<Integer> randomList;
JLabel numberLabel;
JButton sortButton;
#Override
public void init() {
randomList = MyRandom.myRandom();
setSize(400, 400);
setLayout(new FlowLayout());
sortButton = new JButton("Sort");
sortButton.setBounds(50, 0, 50, 10);
sortButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Collections.sort(randomList);
removeAll();
repaint();
}
});
this.add(sortButton);
super.init();
}
#Override
public void paint(Graphics g) {
int y = 20;
for (Integer i : randomList) {
g.drawString(i.toString(), 0, y + 10);
g.fillRect(20, y, (i * 10) / 10, 5);
y = y + 20;
}
}
}
But, I am facing two problems here..
Sort button, which is JButton is not always visible. When i am placing mouse cursor over that sort button place then only it is appearing.
The results are overriding when I am calling repaint() method. As the bellow image
Result Image (As I don't have reputation I am pasting the image link.)
Please help me to solve this problem.
Thank you in Advance.
#Override
public void paint(Graphics g) {
// ..
Should be:
#Override
public void paint(Graphics g) {
super.paint(g); // paints **BG**, border etc.
// ..
Your problem is that you are overridding paint instead of paintComponent, and also you are not calling super.paint/Component (also a good practice, though possibly not 100% necessary here).
Because of how you've overridden paint(), you button is not getting automatically painted when the JApplet is painted
Related
Where to place JOptionPaneShowInputDialog code?
Where to place JOptionPaneShowInputDialog code?Where to place JOptionPaneShowInputDialog code?
Where to place JOptionPaneShowInputDialog code?
Where to place JOptionPaneShowInputDialog code?
I would like to add a JoptionPaneShowInputDialog()(not in code yet) inside the code herebelow.
I can do, but I cannot make the dialog appearing in the black panel,before the recursion.
The dialog appears after the drawing...
public class FractalTree extends JPanel implements ActionListener
{
int x1=350;
int y1=600;
int angle=-90;
int depth=11;
int k=10;
JLabel label_1;
private void drawTree(Graphics g, int x1, int y1, double angle, int depth, int k)
{
if(depth==11)
g.setColor(Color.GRAY);
g.fillRect(100, 600, 1160, 10);
g.setColor(Color.white);
if (depth == 0) return;
((Graphics2D) g).setStroke(new BasicStroke((float) (k*0.9)));
int x2 = x1 + (int) (Math.cos(Math.toRadians(angle)) * depth * 11*Math.random()+1);
int y2 = y1 + (int) (Math.sin(Math.toRadians(angle)) * depth * 11*Math.random()+1);
if(depth<3)
{
g.setColor(Color.green);
}
g.drawLine(x1, y1, x2, y2);
drawTree(g, x2, y2, angle - 19, depth-1,k-1);
drawTree(g, x2, y2, angle + 19, depth-1,k-1);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.white);
drawTree(g,x1,y1,angle,depth,k);
drawTree(g,x1+600,y1,angle,depth,k);
}
public FractalTree()
{
this.setBackground(Color.black);
}
public static void gui()
{
JFrame f=new JFrame("fractal tree");
JLabel label_1=new JLabel("<html>RANDOM TREE<br><center>FRACTAL");
label_1.setForeground(Color.red);
Font font = new Font("Courier", Font.BOLD,25);
label_1.setFont(font);
FractalTree ft=new FractalTree();
f.getContentPane().add(ft);
f.setSize(1500, 1000);
JButton button = new JButton("Close Me");
button.addActionListener(ft);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ft.add(label_1);
ft.add(button);
f.setUndecorated(true);
f.setVisible(true);
}
public static void main(String[] args)
{
gui();
}
#Override
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
}
May I ask some help?
Thanks
The question and intent are some what unclear. What is the purpose of the dialog?
I assume you want to gather some information which can then be passed to the FractalTree to change it's rendering
The question and intent are some what unclear. What is the purpose of the dialog?
I assume you want to gather some information which can then be passed to the FractalTree to change it's rendering, in that case you probably need to put the dialog before the creation of the FractalTree
public static void gui()
{
// You can put the dialog here...
JFrame f=new JFrame("fractal tree");
//...
If you want to change the properties FractalTree after its been displayed, then you probably need to use a JButton and a ActionListener and place the dialog in there ... or provide a second view to gather the properties directly
In fact, the purpose of the dialog box is to ask the recursion level. If I place it like you propose, its ok, but the dialog box appears alone, not in the black panel, and I would like that it appears in the panel...
Let's just be clear, SO is NOT a tutorial or mentoring site. Your problem isn't a technical problem, but an experience one. You should spend more time reading through tutorials like Creating a GUI With Swing and trying things. This is how you will become a better developer and learn to solve your own problems.
Based on your feedback, JOptionPane isn't what you need.
Instead, you need to take a slightly different approach and supply your own input component.
First, you need to change FractalTree so that you can modify the depth property more easily (and set the initial depth to 0 so it will stop drawing)
public class FractalTree extends JPanel implements ActionListener {
private int depth = 0; // set to 0 to stop it from rendering
public void setDepth(int depth) {
this.depth = depth;
repaint();
}
public int getDepth() {
return depth;
}
Next, you need to create your own input component, which can take input from the user and update the tree
public class InputPane extends JPanel {
private FractalTree fractalTree;
private JTextField depthField;
public InputPane(FractalTree fractalTree) {
this.fractalTree = fractalTree;
depthField = new JTextField(10);
depthField.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
String text = depthField.getText().trim();
try {
int value = Integer.parseInt(text);
fractalTree.setDepth(value);
} catch (NumberFormatException exp) {
JOptionPane.showMessageDialog(InputPane.this, text + " is not a valid numerical value");
}
}
});
}
}
Then you want to create a new entry point that can combine the two...
import java.awt.EventQueue;
import javax.swing.JFrame;
public class Main {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
FractalTree tree = new FractalTree();
InputPane input = new InputPane(tree);
JFrame frame = new JFrame();
frame.add(tree);
frame.add(input, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
Yes, this is going to produce a small window, because FractalTree doesn't define any sizing hints, which can be solved by overriding it's getPreferredSize method and returning a more suitable size.
This is going to put you own a "better path", there are still issues you're going to have to solve, because doing it all for you won't help you
I'm having trouble with my jbutton not displaying. If i do not use paintComponent, then my JButtons with images show up no problem. However now, the image does not show up. If i hover over where it should be, the image shows up for one second. So it's like the button is still there, just maybe below the background?
public class Game extends JPanel implements KeyListener, ActionListener {
//layout variables
private ImageIcon right,left,up,down;
private JButton rightButton,leftButton,upButton,downButton;
//play variables
private boolean play=false;
private int score=0;
private int paddleX= 200; //paddle X position
private int paddleY= 300; //paddle Y pos
private int ballX= 210; //ball x position
private int ballY= 260; //ball y position
private int ballXdir=-1; //x direction
private int ballYdir=-2; //y direction
private Timer time; //my timer
public Game() {
Display(); //display the layout
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
time= new Timer(8,this);
time.start();
}
public void Display(){
//setLayout
this.setLayout(null);
//Setting the Images
//right = new ImageIcon(getClass().getResource("images\\rightIcon.png"));
left = new ImageIcon(getClass().getResource("images\\leftIcon.png"));
up = new ImageIcon(getClass().getResource("images\\upIcon.png"));
down = new ImageIcon(getClass().getResource("images\\downIcon.png"));
//Setting the JButtons for the arrow images
rightButton= new JButton("right");
rightButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(paddleX>=400){
paddleX=400;
}
else{
moveRight();
}
repaint();
}
});
//rightButton.setOpaque(false);
//rightButton.setContentAreaFilled(false);
//rightButton.setBorderPainted(false);
leftButton= new JButton(left);
leftButton.setOpaque(false);
leftButton.setContentAreaFilled(false);
leftButton.setBorderPainted(false);
upButton= new JButton(up);
upButton.setOpaque(false);
upButton.setContentAreaFilled(false);
upButton.setBorderPainted(false);
downButton= new JButton(down);
downButton.setOpaque(false);
downButton.setContentAreaFilled(false);
downButton.setBorderPainted(false);
//setting image bounds and adding it to screen
rightButton.setBounds(135,450,50,50);
leftButton.setBounds(45,450,50,50);
upButton.setBounds(90,400,50,50);
downButton.setBounds(90,500,50,50);
//rightButton.addActionListener(this);
leftButton.addActionListener(this);
add(upButton);
add(downButton);
add(leftButton);
add(rightButton);
}
//painting the screen with graphics
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(25,25,425,300); //game area
//drawing the paddle
g.setColor(Color.YELLOW);
g.fillRect(paddleX,paddleY,50,8);
//drawing the ball
g.setColor(Color.PINK);
g.fillOval(ballX,ballY,20,20);
g.dispose();
}
#Override
public void actionPerformed(ActionEvent e) {
time.start();
if(e.getSource()==right) {
if(paddleX>=400){
paddleX=400;
}
else{
moveRight();
}
}
if(e.getSource()==left) {
if(paddleX<35){
paddleX=35;
}
else{
moveLeft();
}
}
repaint();
}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_RIGHT){
if(paddleX>=400){
paddleX=400;
}
else{
moveRight();
}
}
if(e.getKeyCode()==KeyEvent.VK_LEFT){
if(paddleX<35){
paddleX=35;
}
else{
moveLeft();
}
}
}
#Override
public void keyReleased(KeyEvent arg0) {
}
#Override
public void keyTyped(KeyEvent arg0) {
}
public void moveRight(){
play=true;
paddleX+=10;
}
public void moveLeft(){
play=true;
paddleX-=10;
}
}
I highly recommend having a look at Performing Custom Painting and Painting in AWT and Swing as it will explain how the painting system works.
Basically, you are passed a reference to the Graphics context which is currently been used to perform the current paint pass, via the paintComponent method. This is a shared resource. All components involved in the paint pass are passed the same Graphics context.
By calling dispose, you are releasing all the underlying resources for the context, which can, on some systems, prevent other components from been painted.
But they paint when I move my mouse over them
Because components can be painted independently of their parent, but you also call repaint on the parent component, which will, you guessed it, paint it's children.
Recommendations
Create a custom component dedicated solely to performing the custom painting operations (and possible some of the other basic game functions)
Create another component to hold the buttons (and make use of appropriate layouts)
Use a some kind of data model which is shared between them. This model will hold the state of the "actions" (ie up/down/left/right) and the "engine" will use this information to update the state of the game.
Make use of the Key bindings API which will solve the unreliability issues associated with KeyListener
I created this java program and I wanted an output of which if int x and int y are above 100, it would draw a rectangle. But it doesn't. How can I make it work?Is there another line of code I need to add?
Here's my code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class GameSetup extends JPanel implements MouseMotionListener{
public static JFrame njf = new JFrame("Test");
public static int x, y;
public static void main(String[] args){
GameSetup gs = new GameSetup();
njf.add(gs);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
this.setBackground(Color.BLACK);
g.setColor(Color.GREEN);
g.fillRect(150, 75, 200, 100);
g.setColor(Color.ORANGE);
g.drawString("Play", 239, 123);
njf.addMouseListener(new MouseAdapter() {
public void mouseMoved(MouseEvent e) {
x = e.getX();
y = e.getY();
}
});
if(x > 100 && y > 100){
g.drawRect(10, 10, 100, 100);
}
}
public GameSetup(){
njf.setSize(500,500);
njf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
njf.setResizable(false);
njf.setLocationRelativeTo(null);
njf.setVisible(true);
}
#Override
public void mouseDragged(MouseEvent arg0) {
}
#Override
public void mouseMoved(MouseEvent e) {
}
}
Okay, there are several things wrong with the code that you included above.
The first that stood out to me was the way that you are adding the mouse action listener to frame. There are multiple things that are wrong with this.
First of all, you are doing this in the paintComponent method, which, if it works, is still considered to be bad practice because the paintComponent method may be called multiple times. Do that, as pointed out by the comments, in the constructor of the panel.
The second is that you are adding the mouse listener to the frame, not the panel, which doesn't work because the panel is "above" the frame, so the mouse event will only be recognized within the panel. Your best bet here is to add a MouseMotionListener directly to the panel itself.
The third is that you are implementing the MouseMotionListenerinterface in the GameSetup class, but never actually doing anything with this implementation. So what I did was that I got rid of the inner class, and just had the panel be its own MouseMotionListnener
The second thing that is wrong with the code is that the paintComponent method is only called at certain points in time (see this). That means that even though the mouse might have moved within the zone, your paintComponent method isn't being called to update the screen accordingly. For this, you need to call the repaint method for your panel.
The third is that you didn't set a size for your panel, and the default one is 0x0, so you need to set a size of your panel (which should be the same as the frame itself) (if you want to keep the default layout).
All of that being said, here is your code that I fixed up. I added a variable called enteredZone to keep track of if the mouse had previously entered the zone, so that the rectangle would stay up even if the mouse left the zone after entering it (its your choice if you want to keep it). Note that there are other things with this code that might be considered bad practice, but this is enough to get you started:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class GameSetup extends JPanel implements MouseMotionListener {
public static JFrame njf = new JFrame("Test");
public static int x = 0, y = 0;
public static boolean enteredZone = false;
public static void main(String[] args) {
GameSetup gs = new GameSetup();
gs.addMouseMotionListener(gs);
njf.add(gs);
njf.setVisible(true);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.setBackground(Color.BLACK);
g.setColor(Color.GREEN);
g.fillRect(150, 75, 200, 100);
g.setColor(Color.ORANGE);
g.drawString("Play", 239, 123);
if (x > 100 && y > 100 || enteredZone){
g.drawRect(10, 10, 100, 100);
enteredZone = true;
}
}
public GameSetup() {
super();
setSize(500, 500);
njf.setSize(500,500);
njf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
njf.setResizable(false);
njf.setLocationRelativeTo(null);
}
#Override
public void mouseDragged(MouseEvent arg0) {
}
#Override
public void mouseMoved(MouseEvent e) {
x = e.getX();
y = e.getY();
if (x > 100 && y > 100) repaint();
}
}
I want the user of my program to be able to highlight an area on a JFrame to select a group of items on screen. The code I posted below works, but it is very choppy, which becomes quite an eyesore every single time the JFrame repaints. Here's an image of what I'm talking about: http://i1065.photobucket.com/albums/u400/mfgravesjr/choppy%20draw%20rectangle_zpsspqsqnyf.png
Maybe someone here has suggestions to improve my code?
This is the mouseDragged method in MouseMotionListener:
public void mouseDragged(MouseEvent me)
{
if(groupingTerr&&me.getSource()==background)
{
endPoint = MouseInfo.getPointerInfo().getLocation();
topLeftRect = new Point(Math.min(startPoint.x,endPoint.x),Math.min(startPoint.y,endPoint.y));
bottomRightRect = new Point(Math.max(startPoint.x,endPoint.x),Math.max(startPoint.y,endPoint.y));
for(Point p:map.territoryPoints)
{
if(p.x>topLeftRect.x&&p.x<bottomRightRect.x&&p.y>topLeftRect.y&&p.y<bottomRightRect.y)img.getGraphics().drawImage(selectedIco,p.x-selectedIco.getWidth()/2,p.y-selectedIco.getHeight()/2,null);
else img.getGraphics().drawImage(defaultIco,p.x-defaultIco.getWidth()/2,p.y-defaultIco.getHeight()/2,null);
}
background.repaint();
}
}
This is the private overridden JFrame class
private static class DrawableJFrame extends JFrame
{
#Override
public void paint(Graphics g)
{
super.paint(g);
g.setColor(new Color(0,0,0,100));
g.drawRect(topLeftRect.x,topLeftRect.y,bottomRightRect.x-topLeftRect.x,bottomRightRect.y-topLeftRect.y);
g.setColor(new Color(200,10,10,100));
g.fillRect(topLeftRect.x,topLeftRect.y,bottomRightRect.x-topLeftRect.x,bottomRightRect.y-topLeftRect.y);
}
}
The image is original artwork. Please do not use it.
I want to be able to click the JButton and change the next individual ellipse I make to its respective color, Red or Black, from its default Blue. So far I'm able to change the color of all the ellipses I have made.
public class MainClient {
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainClient window = new MainClient();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public MainClient() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 800, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final SpriteField panel = new SpriteField();
panel.setBounds(0, 110, 782, 331);
panel.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
int tX = e.getX();
int tY = e.getY();
panel.CreateObjectAt(tX,tY);
}
});
frame.getContentPane().setLayout(null);
panel.setBackground(Color.LIGHT_GRAY);
frame.getContentPane().add(panel);
final JButton btnRed = new JButton("black");
btnRed.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
panel.setColor(Color.BLACK);
}
});
btnRed.setBounds(229, 500, 97, 25);
frame.getContentPane().add(btnRed);
JButton btnRed_1 = new JButton("red");
btnRed_1.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
panel.setColor(Color.RED);
}
});
btnRed_1.setBounds(342, 500, 97, 25);
frame.getContentPane().add(btnRed_1);
}
}
I have a SriteField Class
public class SpriteField extends JPanel
{
ArrayList<RoundSprite>mSprites = new ArrayList<RoundSprite>();
private Color color = Color.BLUE;
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
AffineTransform tOldTransform = g2.getTransform();
for(RoundSprite tOne:mSprites)
{
tOne.DrawSprite(g2, color);
}
g2.setTransform(tOldTransform);
}
public void CreateObjectAt(int tX, int tY)
{
//make sprite
RoundSprite mLonely = new RoundSprite();
//set position
mLonely.SetPosition(tX, tY);
//add to array
mSprites.add(mLonely);
repaint();
}
public void setColor(Color color)
{
this.color = color;
repaint();
}
}
I have a RoundSprite Class
public class RoundSprite
{
int mX;
int mY;
private Color color;
void DrawSprite(Graphics2D g2, Color color)
{
AffineTransform tOldTransform = g2.getTransform();
g2.setColor(color);
g2.translate(mX, mY); //got it out from the corner
g2.draw(new Ellipse2D.Double(-15, -22, 30, 50));
g2.setTransform(tOldTransform);
}
public void SetPosition(int tX, int tY) //g2.translate
{
mX = tX;
mY = tY;
}
There are three core issues...
One
In order for the panel_1 MouseListener to change the color of the sprites within panel, the MouseListener requires a reference to the panel.
You could declare the panel as final within the initialize method, but I prefer to make the panel a private instance field of the MainClient.
Two
In order to change the color, the SpriteField needs to provide a means by which interested parties can request a change.
This is going to require SpriteField to provide some kind of method that interested parties can call when they need to, for example, a setColor method...
public class SpriteField extends JPanel {
private Color color = Color.BLACK;
//...
public void setColor(Color color) {
this.color = color;
repaint();
}
Then panel_1's MouseListener can now reference the SpriteField and call a method which can produce a change...
panel_1.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("Click");
panel.setColor(Color.BLUE);
}
});
Three
You need some way to tell the sprite what color it should be...
This one depends on what it is you want to achieve...
If you want to paint ALL the sprites the same color, then you need some way to tell the sprites which color they should use, for example, you could change the DrawSprite method to accept a Color parameter...
public class RoundSprite {
//...
void DrawSprite(Graphics2D g2, Color color) {
And within the SpriteField paintComponent, pass the color to the sprite
public class SpriteField extends JPanel {
//...
private Color color = Color.BLACK;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
AffineTransform tOldTransform = g2.getTransform();
for (RoundSprite tOne : mSprites) {
tOne.DrawSprite(g2, color);
}
g2.setTransform(tOldTransform);
}
Now, this will paint ALL the sprites within the field the same color, if you want to change the color of individual sprites, this comes infinitely more complicated...
Lets leave aside the issues of selecting a sprite for the moment...
Basically, you would need to apply the same principle from point Two to the RoundSprite class.
You would need to supply a method that could set/get the desired color. You would need to store this value in an instance field of the RoundSprite class and when DrawSprite is called, apply that Color to the Graphics context.
This would mean that SpriteField won't need to perform any color management, beyond passing the request for change from a caller to the selected sprite, so it would still need a setColor method...
Side Notes...
You might like to have a read through Code Conventions for the Java TM Programming Language, it will make it easier for people to read your code and for you to read others
Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify
Oh, and you realise that there already is a JButton class that probably should be used instead of a JPanel with a MouseListener....?