I'm a beginner in Java, and I'm using book to learn, now I'm in the first GUI topics, and I've got a problem. I don't know why but I can't see text that I'm trying to put in the frame, this is the code:
import java.awt.*;
import javax.swing.*;
public class Ramka {
public static void main(String[] args)
{
JFrame ramka = new JFrame();
ramka.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ramka.setTitle("Frame");
ramka.setVisible(true);
Toolkit zestaw = Toolkit.getDefaultToolkit();
Dimension rozmiar = zestaw.getScreenSize();
int szerokosc = rozmiar.width;
int wysokosc = rozmiar.height;
ramka.setSize(szerokosc, wysokosc);
}
}
class Ramkatekst extends JComponent{
Toolkit zestaw = Toolkit.getDefaultToolkit();
Dimension rozmiar = zestaw.getScreenSize();
int szerokosc = rozmiar.width/2;
int wysokosc = rozmiar.height/2;
public void paintComponent(Graphics g)
{
g.drawString(" Sample text",szerokosc, wysokosc );
}
}
As #pshemo points out, Ramkatekst is never used. You need to create an instance of it and add it to your JFrame "ramka". So simply add this line at the end of your main method:
ramka.add(new Ramkatekst());
Related
I have a draw class that extends JPanel and has a void method called drawing with repaint() in it.
public class draw extends JPanel {
public draw(int position_x, int position_y, int width, int height) {
positionx = position_x;
positiony = position_y;
this.width = width;
this.height = height;
}
public void drawing() {
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillRect(positionx, positiony, width, height);
}
}
So, my intention is create a lot of this rectangles in a JPanel so they create a graphic bar.
public class coin_launcher {
public static void main(String[] args) {
JFrame frame = new JFrame("Coin Launcher");
frame.setVisible(true);
frame.setSize(1920, 1080);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
draw object = new draw(2,2,100,2);
frame.add(object);
object.drawing();
draw object2 = new draw(2,6,200,2);
frame.add(object2);
object2.drawing();
}
}
The problem is that when I call drawing() in both of the objects only one gets drawn.
If use the debugger its only the first one, if I dont, its only the second one. I need to make 100 bars but it literally repaints the JPanel every time, how can I add different draw class in one JPanel without erasing the others?
JFrame uses a BorderLayout by default, this means that only the last component added (to the default centre position) will be managed by the layout.
See BorderLayout for more details.
An immediate solution might be to use a different layout manager, but I would argue that's the wrong solution.
Instead, you should have ONE component, which is capable of paint multiple bars, based on the data available from a "model"
This decouples the source of the data from the presentation of the data, allowing to produce multiple different implementations of these, which shouldn't break the other.
In this case, the "view" shouldn't care how the data is obtained or marinated, only that it conforms to a specified contract, like wise the data doesn't care how its presented.
See Model-View-Controller for more details
This answer is a very basic and simplified example of
"you should have ONE component, which is capable of paint multiple
bars, based on the data available from a "model"
quoted from MadProgrammer's answer.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.Arrays;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class CoinLauncher {
public static void main(String[] args) {
JFrame frame = new JFrame("Coin Launcher");
frame.setSize(920, 480);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//data to be painted. for better implementation use a model class that
//encapsulates the data
Rectangle[] bars = {
new Rectangle(2,2,100,2),
new Rectangle(2,6,200,2),
};
Draw object = new Draw(Arrays.asList(bars));
frame.add(object);
frame.setVisible(true);
}
}
class Draw extends JPanel {
private final List<Rectangle> bars;
Draw(List<Rectangle> bars) {
this.bars = bars;
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLUE);
for(Rectangle bar : bars){
g.fillRect(bar.x, bar.y, bar.width, bar.height);
}
}
}
Implementing a model to encapsulate data need for the view, can be as simple as :
public class CoinLauncher {
public static void main(String[] args) {
JFrame frame = new JFrame("Coin Launcher");
frame.setSize(920, 480);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Model model = new Model();
model.addBar( new Rectangle(2,2,100,2) );
model.addBar( new Rectangle(2,6,200,2) );
Draw object = new Draw(model);
frame.add(object);
frame.setVisible(true);
}
}
class Draw extends JPanel {
private final List<Rectangle> bars;
Draw(Model model) {
bars = model.getBars();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLUE);
for(Rectangle bar : bars){
g.fillRect(bar.x, bar.y, bar.width, bar.height);
}
}
}
class Model {
private final List<Rectangle> bars;
Model(){
bars = new ArrayList<>();
}
void addBar(Rectangle rectangle){
bars.add(rectangle);
}
List<Rectangle> getBars() { return bars; }
}
I need help with this code. My g.drawLine(0,0,300,300) is not working. It was working until monday, I don't know what is going wrong. I use the g.drawLine(0,0,300,300) in order to test before using the plota_pixel() method. g.drawLine(0,0,300,300) shoud print a line from (0,0) to (300,300) on the Jpanel panel
MainView Class:
package alexandre.VIEW;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainView {
private JFrame janela;
public JPanel panel;
public MainView()
{
janela = new JFrame("Exercicio 15/09");
janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new JPanel();
this.ShowView();
}
public void ShowView()
{
janela.pack();
janela.setSize(750,600);
janela.setLayout(null);
janela.add(panel);
panel.setBounds(0,0,710,600);
janela.setVisible(true);
System.out.println("OIdsazxc");
Graphics g = panel.getGraphics();
g.setColor(Color.BLACK);
g.drawLine(0,0,300,300);
}
public void plota_pixel(int x, int y)
{
Graphics g = panel.getGraphics();
g.drawLine(x, y, x, y);
}
}
Starter Class:
package alexandre.CONTROL;
import alexandre.VIEW.MainView;
public class Starter {
public static void main(String[] args) {
MainView view = new MainView();
view.ShowView();
}
}
Using and drawing with the Graphics object from panel.getGraphics() does not work (see below links for the "why"). You will have to override the method "paintComponent" for the the JPanel, where the input parameter is the Graphics object
(Also quick note - standard method naming has the first letter lowercase so ShowView() should be showView())
public MainView()
{
janela = new JFrame("Exercicio 15/09");
janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new JPanel() {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.drawLine(0,0,300,300);
}
};
this.showView();
}
public void showView() {
janela.pack();
janela.setSize(750, 600);
janela.setLayout(null);
janela.add(panel);
panel.setBounds(0, 0, 710, 600);
panel.setVisible(true);
janela.repaint();
}
Check out the following stack overflow question
Drawing an object using getGraphics() without extending JFrame
And this resource (it's also in the linked question)
http://docs.oracle.com/javase/tutorial/uiswing/painting/
You should set the panel visible as the last thing in the ShowViewmethod.
public void ShowView()
{
//your code
janela.setVisible(true);
}
I am learning java swing and am having trouble with the following program. It creates a small frame with a quit button at top. The objective is to display coordinates wherever the mouse is clicked. When I click the mouse 2 unwanted things are happening:
the quit button is overridden by the mouse clicks and it no longer responds (instead of responding to event and quitting, it displays coordinates on top of the quit button).
when I click at a new location, the coordinates from the old location persist.
I used removeAll() and revalidate() before doing repaint() based on this discussion but that has not helped. This code is taken from here and the code to says to research online documentation for why this is happening.
Any pointers?
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.Color;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.BorderLayout;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JLabel;
public class QuitCoordinateTest {
public static void main(String[] args){
GUI gui = new GUI();
}
}
class MyFrame extends JFrame implements ActionListener{
int clickX;
int clickY;
public void paint(Graphics g){
g.drawString("" + clickX + ", " + clickY, clickX, clickY);
}
public void actionPerformed(ActionEvent e){
System.exit(0);
}
}
//=======================================================//
class GUI extends MyFrame {
JButton quitButton = new JButton("Quit");
public GUI(){
MyFrame displayWindow = new MyFrame();
displayWindow.setTitle("Title");
/*
JPanel buttonPanel = new JPanel();
buttonPanel.add(quitButton);
displayWindow.getContentPane().add(buttonPanel,BorderLayout.NORTH);
JPanel textPanel = new JPanel();
*/
displayWindow.getContentPane().add(quitButton,BorderLayout.NORTH);
quitButton.addActionListener(displayWindow);
displayWindow.setSize(201,201);
displayWindow.setVisible(true);
// displayWindow.pack();
displayWindow.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
displayWindow.addMouseListener(new MouseProc(displayWindow));
}//end constructor
}//end class GUI definition
//=======================================================//
//This listener class monitors for mouse presses and
// displays the coordinates of the mouse pointer when the
// mouse is pressed on the source object.
class MouseProc extends MouseAdapter{
MyFrame refToWin;
MouseProc(MyFrame inWin){
refToWin = inWin;
}
//Override the mousePressed method to determine and
// display the coordinates when the mouse is pressed.
public void mousePressed(MouseEvent e){
refToWin.removeAll();
refToWin.clickX = e.getX();
refToWin.clickY = e.getY();
//Force the JFrame object to be repainted in order to
// display the coordinate information.
refToWin.removeAll();
refToWin.validate();
refToWin.repaint();
}
}
repaint() is working fine.
Avoid drawing directly on the JFrame.
Instead draw in the protected void paintComponent(Graphics g) method override of a JPanel that is then displayed in your JFrame.
Be sure to call the super's paintComponent(g) method inside of your paintComponent override -- this will erase the old images and is the reason for one of your problems.
Use reasonable comments in your code. Too many comments and too much text distracts and makes understanding your code harder, not easier.
Calling removeAll() on your JFrame will do just that -- remove all components including your button. Why are you calling this? Are you sure that you want to call this method?
A minor nitpick -- you'll want to avoid directly setting the fields of another class, such as your clickX and clickY fields. Instead, make them private, and only allow outside classes to modify them through public methods. While it may not matter much for this small program, it will matter greatly when you start scaling up your programming and create large programs with complex interactions. The key to success here will be to limit and control all communication between classes to avoid hard to detect side effects.
For example, something like...
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
String str = String.format("[%d, %d]", clickX, clickY);
g.drawString(str, clickX, clickY);
}
public int getClickX() {
return clickX;
}
public void setClickX(int clickX) {
this.clickX = clickX;
}
public int getClickY() {
return clickY;
}
public void setClickY(int clickY) {
this.clickY = clickY;
}
For example
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class DetectClicks extends JPanel {
private static final int PREF_W = 800;
private static final int PREF_H = 650;
private int clickX;
private int clickY;
public DetectClicks() {
MyMouseListener mouseAdapter = new MyMouseListener(this);
addMouseListener(mouseAdapter);
addMouseMotionListener(mouseAdapter); // to allow dragging!
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
String str = String.format("[%d, %d]", clickX, clickY);
g.drawString(str, clickX, clickY);
}
public int getClickX() {
return clickX;
}
public void setClickX(int clickX) {
this.clickX = clickX;
}
public int getClickY() {
return clickY;
}
public void setClickY(int clickY) {
this.clickY = clickY;
}
private static void createAndShowGui() {
DetectClicks mainPanel = new DetectClicks();
JFrame frame = new JFrame("DetectClicks");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class MyMouseListener extends MouseAdapter {
private DetectClicks detectClicks;
public MyMouseListener(DetectClicks detectClicks) {
this.detectClicks = detectClicks;
}
#Override
public void mousePressed(MouseEvent evt) {
showPoint(evt);
}
#Override
public void mouseDragged(MouseEvent evt) {
showPoint(evt);
}
private void showPoint(MouseEvent evt) {
detectClicks.setClickX(evt.getX());
detectClicks.setClickY(evt.getY());
detectClicks.repaint();
}
}
Your event is getting consumed by the handler that prints the coordinates, you need to redispatch the event so that the button can see it. You can do it like this, inside the coordinate display event handler:
Component c = e.getComponent();
c.getParent().dispatchEvent( e );
Also, I'd be tempted to use the glass pane of the frame, and put a JLabel on it with the co-ordinates rather than messing with the paint method.
you don't have to use any of repaint(),invalidate() etc.
i highly recommend to use
SwingUtilities.invokeLater(new Runnable() {
public void run() {
//TODO udpdate UI compontents, layouts etc.
}
});
this guarantees that UI components update on real time. Because we don't know when the system update UI hierarchy so we can't force it. This allow system to determine by it's self.
I've been taking AP Computer Science this year as a sophomore in high school and we mainly cover material like loops, classes, methods, general CS logic, and some math stuff. I am missing what I really loved about coding in the first place, making games. Now every game I have made had some sort of way to manage it whether it was using timers in visual basic or a XNA plugin for c# that setup a update method for me. The problem is I have not learned how to do this for java in my course. I've read up a little on threads and implements runnable but i'm not really sure where I'm going with it.
Class 1
import java.awt.FlowLayout;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class GFXScreen extends JFrame
{
/**
* #param screenHeigth
* #param screenHeigth
* #param The file name of the image. Make sure to include the extension type also
* #param The title at the top of the running screen
* #param The height of the screen
* #param The width of the screen
*/
public GFXScreen(String fileName, String screenTitle, int screenHeight, int screenWidth)
{
setLayout(new FlowLayout());
image1 = new ImageIcon(getClass().getResource(fileName));
label1 = new JLabel(image1);
this.add(label1);
//Set up JFrame
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
this.setTitle(screenTitle);
this.setSize(screenWidth, screenHeight);
}
/**
* #param desired amount to move picture
*/
public void updatePic(int increment)
{
//update pos
label1.setBounds(label1.bounds().x, label1.bounds().y - increment,
label1.bounds().width, label1.bounds().height);
}
private ImageIcon image1;
private JLabel label1;
}
Class 2
public class MainClass implements Runnable {
public static void main(String[] args)
{
(new Thread(new MainClass())).start();
GFXScreen gfx = new GFXScreen("pixel_man.png", "pixel_Man", 1000, 1000);
}
public void run()
{
gfx.updatePic(1);
}
}
In this instance what I want to happen is, I want a picture that starts in the top to slowly move down smoothly to the bottom. How would i do this?
Suggestions:
Again, a Swing Timer works well for simple Swing animations or simple game loops. It may not be the greatest choice for complex or rigorous tame loops as its timing is not precise.
Most game loops will not be absolutely precise with time slices
And so your game model should take this into consideration and should note absolute time slices and use that information in its physics engine or animation.
If you must use background threading, do take care that most all Swing calls are made on the Swing event thread. To do otherwise will invite pernicious infrequent and difficult to debug program-ending exceptions. For more details on this, please read Concurrency in Swing.
I avoid using null layouts, except when animating components, as this will allow my animation engine to place the component absolutely.
When posting code here for us to test, it's best to avoid code that uses local images. Either have the code use an image easily available to all as a URL or create your own image in your code (see below for a simple example).
Your compiler should be complaining to you about your using deprecated methods, such as bounds(...), and more importantly, you should heed those complaints as they're there for a reason and suggest increased risk and danger if you use them. So don't use those methods, but instead check the Java API for better substitutes.
Just my own personal pet peeve -- please indicate that you've at least read our comments. No one likes putting effort and consideration into trying to help, only to be ignored. I almost didn't post this answer because of this.
For example:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
#SuppressWarnings("serial")
public class GfxPanel extends JPanel {
private static final int BI_WIDTH = 26;
private static final int BI_HEIGHT = BI_WIDTH;
private static final int GAP = 6;
private static final Point INITIAL_LOCATION = new Point(0, 0);
private static final int TIMER_DELAY = 40;
public static final int STEP = 1;
private ImageIcon image1;
private JLabel label1;
private Point labelLocation = INITIAL_LOCATION;
private int prefW;
private int prefH;
private Timer timer;
public GfxPanel(int width, int height) {
// the only time I use null layouts is for component animation.
setLayout(null);
this.prefW = width;
this.prefH = height;
// My program creates its image so you can run it without an image file
image1 = new ImageIcon(createMyImage());
label1 = new JLabel(image1);
label1.setSize(label1.getPreferredSize());
label1.setLocation(labelLocation);
this.add(label1);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(prefW, prefH);
}
public void startAnimation() {
if (timer != null && timer.isRunning()) {
timer.stop();
}
labelLocation = INITIAL_LOCATION;
timer = new Timer(TIMER_DELAY, new TimerListener());
timer.start();
}
// My program creates its image so you can run it without an image file
private Image createMyImage() {
BufferedImage bi = new BufferedImage(BI_WIDTH, BI_HEIGHT,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = bi.createGraphics();
g2.setColor(Color.red);
g2.fillRect(0, 0, BI_WIDTH, BI_HEIGHT);
g2.setColor(Color.blue);
int x = GAP;
int y = x;
int width = BI_WIDTH - 2 * GAP;
int height = BI_HEIGHT - 2 * GAP;
g2.fillRect(x, y, width, height);
g2.dispose();
return bi;
}
private class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
int x = labelLocation.x + STEP;
int y = labelLocation.y + STEP;
labelLocation = new Point(x, y);
label1.setLocation(labelLocation);
repaint();
if (x + BI_WIDTH > getWidth() || y + BI_HEIGHT > getHeight()) {
System.out.println("Stopping Timer");
((Timer) e.getSource()).stop();
}
}
}
private static void createAndShowGui() {
final GfxPanel gfxPanel = new GfxPanel(900, 750);
JButton button = new JButton(new AbstractAction("Animate") {
#Override
public void actionPerformed(ActionEvent arg0) {
gfxPanel.startAnimation();
}
});
JPanel buttonPanel = new JPanel();
buttonPanel.add(button);
JFrame frame = new JFrame("GFXScreen");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(gfxPanel);
frame.getContentPane().add(buttonPanel, BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
What I always use is an infinite loop that calls an update method each iteration, in that method, you would do whatever was required to update the state of the game or render a GUI.
Example
public static void main(String[] args){
// Initialise game
while(true){
updateGame();
}
}
public static void updateGame(){
// Update things here.
}
What I also do ,which is a little more complex, is create and interface called IUpdateListener and have certain classes that are specialised for a certain element of the game. I would example have an InputListener, an AIListener, each handling a certain element of game updating.
public interface IUpdateListener{
public void update();
}
public class Main{
public static ArrayList<IUpdateListener> listeners = new ArrayList<IUpdateListener>();
public static void main(String[] args){
listeners.add(new InputListener());
while(true){
for(IUpdateListener listener : listeners){
listener.update();
}
}
}
}
public class InputListener implements IUpdateListener{
public void update(){
// Handle user input here etc
}
}
I'm trying to get mutiple images in 'GetImage' class, and disply them in the main class.
Can anybody show me an example how to do it?? I tried bunch of other samples but they didn't work since I have two classes.
Here is one that I tried.
main clss:
import java.awt.*;
import hsa.*;
public class Test
{
static Console c;
public void Display()
{
GetImage c = new GetImage();
c.paint(g);
}
public Test()
{
c = new Console ();
}
public static void main (String[] args) throws Exception
{
Test = new Test();
a.Display();
}
}
seperate class:
import java.awt.*;
import hsa.Console;
import java.awt.event.*;
public class GetImage extends Frame
{
Image image;
String imageName = "ImageFileName.jpg";
public void paint (Graphics g)
{
Toolkit tool = Toolkit.getDefaultToolkit ();
image = tool.getImage (imageName);
g.drawImage (image, 30, 30, this); // location of the image
g.drawString (imageName, 100, 50); // location of the name
}
}
I'm not very familiar with the hsa package, but some quick googling says it's an educational package from some company that has since gone out of business, correct me if I'm wrong. So personally I'd try to avoid using any of their stuff if you can.
If you have to use this for school or something then you probably want to stick entirely with their package instead of mix and matching hsa with awt. Something like this might accomplish what you want, but again I'm not familiar with the hsa package.
import java.awt.*;
import hsa.*;
public class Test
{
static Console c;
public void Display()
{
GetImage gI = new GetImage(c,25,80,12);
}
public Test()
{
c = new Console ();
}
public static void main (String[] args) throws Exception
{
Test = new Test();
a.Display();
}
}
import java.awt.*;
import hsa.ConsoleCanvasGraphics;
import java.awt.event.*;
public class GetImage extends ConsoleCanvasGraphics
{
Image image, image2;
String imageName = "ImageFileName.jpg", image2Name = "Image2FileName.jpg";
public GetImage(ConsoleParent parent, int rows, int columns, int fontSize)
{
Toolkit tool = Toolkit.getDefaultToolkit ();
image = tool.getImage (imageName);
image2 = tool.getImage (image2Name);
super(parent,rows,columns,fontSize);
drawImage(image,30,30,this);
drawImage(image2,30,60,this);
drawString(imageName,100,50,new Font("TimesRoman", Font.PLAIN, 20),Color.BLACK);
drawString(image2Name,100,80,new Font("TimesRoman", Font.PLAIN, 20),Color.BLACK);
}
}
Again, I'd try to avoid hsa myself, but if you're set on using it and need to have two separate classes in your program then the above should be a rough outline of something that might work.