Results 1 to 10 of 10
  1. #1
    ImTroyMiller is offline Member
    Join Date
    Jan 2014
    Posts
    20
    Rep Power
    0

    Question Graphics smearing in JFrame

    I'm using this code to "attempt" to place my game that's currently using the Slick2D game engine into a windowed game that is independent of native packages.

    When I run it, it smears the graphics. The code below will show that the drawstring method is constantly placing the new string(which is assign by moving the mouse or pressing mouse buttons/keyboard keys) over the old string, and it's causing a blurry pileup.

    Is there a way to clear the JFrame each time the draw() method is called? Is there a better way to do this?

    Java Code:
    import java.awt.BorderLayout;
    import java.awt.DisplayMode;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.GraphicsDevice;
    import java.awt.GraphicsEnvironment;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    import java.awt.event.MouseMotionListener;
    import java.awt.event.MouseWheelEvent;
    import java.awt.event.MouseWheelListener;
    import javax.swing.JFrame;
    
    public class GameCore implements KeyListener, MouseMotionListener, MouseListener, MouseWheelListener {
    
    	private boolean running;
    	GraphicsDevice[] devices;
    	DisplayMode oldDisplayMode;
    	JFrame frame;
    	boolean mainScreenOn;
    	static GraphicsEnvironment ge;
    	private String inp = "";
    
    	public static void main(String[] args) {
    		new GameCore().run();
    	}
    
    	public void stop() {
    		running = false;
    	}
    
    	public void run() {
    		init();
    		gameLoop();
    	}
    
    	public void gameLoop() {
    		long startTime = System.currentTimeMillis();
    		long cumTime = startTime;
    		while (running) {
    			long timePassed = System.currentTimeMillis() - cumTime;
    			cumTime += timePassed;
    			update(timePassed);
    			Graphics g = frame.getGraphics();
    			drawer(g);
    			try {
    				Thread.sleep(20);
    			} catch (Exception ex) {
    			}
    		}
    	}
    
    	public void init() {
    		running = true;
    		ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    		devices = ge.getScreenDevices();
    		frame = new JFrame(devices[0].getDefaultConfiguration());
    		frame = new JFrame("Game");
    		frame.getContentPane().setLayout(new BorderLayout());
    		frame.setSize(600, 600);
    		frame.setResizable(false);
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		frame.setVisible(true);
    		frame.addMouseListener(this);
    		frame.addMouseMotionListener(this);
    		frame.addMouseWheelListener(this);
    		frame.addKeyListener(this);
    		System.out.println("Initialization happens one time.");
    	}
    	
    	public void update(long timePassed){
    	}
    
    	public void drawer(Graphics g) {
    		Graphics2D g2 = (Graphics2D) g;
    		g2.drawString(inp, 100, 100);
    		System.out.println("This loops");
    	}
    
    	public void keyPressed(KeyEvent e) {
    		int keyCode = e.getKeyCode();
    		if (keyCode == KeyEvent.VK_ESCAPE) {
    			stop();
    		} else {
    			inp = "Pressed: " + KeyEvent.getKeyText(keyCode);
    			e.consume();
    		}
    		if (e.getKeyCode() == KeyEvent.VK_F12) {
    			if (mainScreenOn) {
    				mainScreenOn = false;
    				mainScreenTurnOff();
    			} else {
    				mainScreenTurnOn();
    				mainScreenOn = true;
    			}
    		}
    	}
    
    	private void mainScreenTurnOn() {
    		oldDisplayMode = devices[0].getDisplayMode();
    		if (devices[0].isFullScreenSupported()) {
    			devices[0].setFullScreenWindow(frame);
    		}
    		DisplayMode dm = new DisplayMode(800, 600, 32, 60);
    		if (devices[0].isDisplayChangeSupported())
    			devices[0].setDisplayMode(dm);
    	}
    
    	private void mainScreenTurnOff() {
    		devices[0].setDisplayMode(oldDisplayMode);
    	}
    
    	public void keyReleased(KeyEvent e) {
    		int keyCode = e.getKeyCode();
    		inp = "Released: " + KeyEvent.getKeyText(keyCode);
    		e.consume();
    	}
    
    	public void keyTyped(KeyEvent e) {
    		e.consume();
    	}
    
    	public void mouseWheelMoved(MouseWheelEvent e) {
    		inp = "You are spinning the mouse wheel.";
    	}
    
    	public void mouseClicked(MouseEvent e) {
    	}
    
    	public void mouseEntered(MouseEvent e) {
    	}
    
    	public void mouseExited(MouseEvent e) {
    	}
    
    	public void mousePressed(MouseEvent e) {
    		inp = "You pressed the mouse.";
    	}
    
    	public void mouseReleased(MouseEvent e) {
    		inp = "You released the mouse.";
    	}
    
    	public void mouseDragged(MouseEvent e) {
    		inp = "You are dragging the mouse.";
    	}
    
    	public void mouseMoved(MouseEvent e) {
    		inp = "You are moving the mouse.";
    	}
    
    }

  2. #2
    gimbal2 is offline Just a guy
    Join Date
    Jun 2013
    Location
    Netherlands
    Posts
    3,900
    Rep Power
    5

    Default Re: Graphics smearing in JFrame

    Going from Slick2d back to Java2d/Swing is a huge step back and you'll be treated to other problems, such as inconsistent performance across different machines. I would seriously reconsider your choices.

    Of course there is a way to clear the entire drawable area: draw a black square large enough to replace the entire thing. Me myself I had a different strategy that was a little smarter (and thus harder to program): if there were only a few things to redraw in a single frame then I would only redraw the area that would cover the old position and the new position of the items that moved. If there are too many things that moved, or the distance between those two items was so great that there wasn't even any overlap between the old position and the new position, I'd fall back to the easy solution of just clearing the entire drawable area.

    That of course requires that you can efficiently know what "exists" within a certain rectangle boundary; a proper datastructure for the world data is a requirement to be able to ask such questions.
    "Syntactic sugar causes cancer of the semicolon." -- Alan Perlis

  3. #3
    ImTroyMiller is offline Member
    Join Date
    Jan 2014
    Posts
    20
    Rep Power
    0

    Question Re: Graphics smearing in JFrame

    Thank you for answering. I also have this other program that uses these three classes to create a nice full screen application. Is there anyway that I could change this from full screen to a window?

    Java Code:
    import java.awt.Color;
    import java.awt.DisplayMode;
    import java.awt.Font;
    import java.awt.Graphics2D;
    import java.awt.Window;
    
    public abstract class MyCore {
    
    	private static DisplayMode modes[] = {
    		new DisplayMode(1920, 1080, 32, 0),
    		new DisplayMode(1920, 1080, 24, 0),
    		new DisplayMode(1920, 1080, 16, 0),
    		new DisplayMode(800, 600, 32, 0),
    		new DisplayMode(800, 600, 24, 0),
    		new DisplayMode(800, 600, 16, 0),
    		new DisplayMode(640, 480, 32, 0),
    		new DisplayMode(640, 480, 24, 0),
    		new DisplayMode(640, 480, 16, 0),
    	};
    	private boolean running;
    	protected ScreenManager s;
    	
    	public void stop(){
    		running = false;		
    	}
    	
    	public void run(){
    		try{
    			init();
    			gameLoop();
    		}finally{
    			s.restoreScreen();
    		}
    	}
    	
    	public void init(){
    		s = new ScreenManager();
    		DisplayMode dm = s.findFirstCompatibleMode(modes);
    		s.setFullScreen(dm);
    		Window w = s.getFullScreenWindow();
    		w.setFont(new Font("Arial", Font.PLAIN, 20));
    		w.setBackground(Color.GREEN);
    		w.setForeground(Color.WHITE);
    		running = true;
    	}
    	
    	public void gameLoop(){
    		long startTime = System.currentTimeMillis();
    		long cumTime = startTime;
    		while(running){
    			long timePassed = System.currentTimeMillis() - cumTime;
    			cumTime += timePassed;
    			update(timePassed);
    			Graphics2D g = s.getGraphics();
    			drawer(g);
    			g.dispose();
    			s.update();
    			try{
    				Thread.sleep(20);
    			}catch(Exception ex){}
    		}
    	}
    	
    	public void update(long timePassed){
    	}
    	
    	public abstract void drawer(Graphics2D g);	
    	
    }
    Java Code:
    import java.awt.DisplayMode;
    import java.awt.Graphics2D;
    import java.awt.GraphicsConfiguration;
    import java.awt.GraphicsDevice;
    import java.awt.GraphicsEnvironment;
    import java.awt.Window;
    import java.awt.image.BufferStrategy;
    import java.awt.image.BufferedImage;
    import javax.swing.JFrame;
    
    public class ScreenManager {
    	
    	private GraphicsDevice vc;
    	
    	public ScreenManager(){
    		GraphicsEnvironment ev = GraphicsEnvironment.getLocalGraphicsEnvironment();
    		vc = ev.getDefaultScreenDevice();
    	}
    	
    	public DisplayMode[] getCompatibleDisplayModes(){
    		return vc.getDisplayModes();
    	}
    
    	public DisplayMode findFirstCompatibleMode(DisplayMode modes[]){
    		 DisplayMode goodModes[] = vc.getDisplayModes();
    		 for (int x=0; x < modes.length; x++){
    			 for(int y=0; y < goodModes.length; y++){
    				 if(displayModesMatch(modes[x], goodModes[y])){
    					 return modes[x];
    				 }
    			 }
    		 }
    		 return null;
    	}
    	
    	public DisplayMode getCurrentDisplayMode(){
    		return vc.getDisplayMode();
    	}
    	
    	public boolean displayModesMatch(DisplayMode m1, DisplayMode m2){
    		if(m1.getWidth() != m2.getWidth() || m1.getHeight() != m2.getHeight()){
    			return false;
    		}
    		if(m1.getBitDepth() != DisplayMode.BIT_DEPTH_MULTI && m2.getBitDepth() != DisplayMode.BIT_DEPTH_MULTI && m1.getBitDepth() != m2.getBitDepth()){
    			return false;
    		}
    		if(m1.getRefreshRate() != DisplayMode.REFRESH_RATE_UNKNOWN && m2.getRefreshRate() != DisplayMode.REFRESH_RATE_UNKNOWN && m1.getRefreshRate() != m2.getRefreshRate()){
    			return false;
    		}
    		return true;
    	}
    	
    	public void setFullScreen(DisplayMode dm){
    		JFrame f = new JFrame();
    		f.setUndecorated(true);
    		f.setIgnoreRepaint(true);
    		f.setResizable(false);
    		vc.setFullScreenWindow(f);
    		if(dm != null && vc.isDisplayChangeSupported()){
    			try{
    				vc.setDisplayMode(dm);
    			}catch(Exception ex){}
    		}
    		f.createBufferStrategy(2);
    	}
    	
    	public Graphics2D getGraphics(){
    		Window w = vc.getFullScreenWindow();
    		if(w != null){
    			BufferStrategy s = w.getBufferStrategy();
    			return (Graphics2D)s.getDrawGraphics();
    		}else{
    			return null;
    		}
    	}
    	
    	public void update(){
    		Window w = vc.getFullScreenWindow();
    		if (w != null){
    			BufferStrategy s = w.getBufferStrategy();
    			if (!s.contentsLost()){
    				s.show();
    			}
    		}
    	}
    	
    	public Window getFullScreenWindow(){
    		return vc.getFullScreenWindow();
    	}
    	
    	public int getWidth(){
    		Window w = vc.getFullScreenWindow();
    		if(w != null){
    			return w.getWidth();
    		}else{
    			return 0;
    		}
    	}
    	
    	public int getHeight(){
    		Window w = vc.getFullScreenWindow();
    		if(w != null){
    			return w.getHeight();
    		}else{
    			return 0;
    		}
    	}
    	
    	public void restoreScreen(){
    		Window w = vc.getFullScreenWindow();
    		if (w != null){
    			w.dispose();
    		}
    		vc.setFullScreenWindow(null);
    	}
    	
    	public BufferedImage createCompatibleImage(int width, int height, int trans){
    		Window w = vc.getFullScreenWindow();
    		if(w != null){
    			GraphicsConfiguration gc = w.getGraphicsConfiguration();
    			return gc.createCompatibleImage(width, height, trans);
    		}
    		return null;
    	}
    	
    	
    }
    Java Code:
    import java.awt.Graphics2D;
    import java.awt.Window;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    
    public class MyKeys extends MyCore implements KeyListener {
    
    	public static void main(String[] args) {
    		new MyKeys().run();
    	}
    	
    	private String mess = "";
    	
    	public void init(){
    		super.init();
    		Window w = s.getFullScreenWindow();
    		w.setFocusTraversalKeysEnabled(false);
    		w.addKeyListener(this);
    		mess = "Press ESC to exit.";
    	}
    	
    	public void keyPressed(KeyEvent e){
    		int keyCode = e.getKeyCode();
    		if(keyCode == KeyEvent.VK_ESCAPE){
    			stop();
    		}else{
    			mess = "Pressed: " + KeyEvent.getKeyText(keyCode);
    			e.consume();
    		}
    	}
    
    	public void keyReleased(KeyEvent e){
    		int keyCode = e.getKeyCode();
    		mess = "Released: " + KeyEvent.getKeyText(keyCode);
    		e.consume();
    	}
    
    	public void keyTyped(KeyEvent e) {
    		e.consume();
    	}
    
    	public synchronized void drawer(Graphics2D g) {
    		Window w = s.getFullScreenWindow();
    		g.setColor(w.getBackground());
    		g.drawString(mess, 200, 200);
    	}
    	
    }

  4. #4
    ImTroyMiller is offline Member
    Join Date
    Jan 2014
    Posts
    20
    Rep Power
    0

    Thumbs up Re: Graphics smearing in JFrame

    Alright, I see what your talking about.

    I just added this code in my drawer method, right after "Graphics2D g2 = (Graphics2D) g;"

    Java Code:
    g2.setColor(Color.WHITE);
    g2.fillRect(0, 0, frame.getWidth(), frame.getHeight());
    g2.setColor(frame.getForeground());
    It did exactly what I wanted, but it's very slow and flickering. In addition, I think the keys weren't working as well.

    I'm going to stick with Slick2D, at least for the time being. The reason I want to move out of it, is mainly because I only have five basic classes; three for the character and two for basic types of object in my game, a main class that has the key/mouse listeners and the main game loop(this class loads all of the images and renders them), and then another class that holds all of the levels(it basically just has methods that has positions of items for each level), and that's it.

    Is Slick2D really needed for such a simple game?

  5. #5
    jim829 is offline Senior Member
    Join Date
    Jan 2013
    Location
    Northern Virginia, United States
    Posts
    3,534
    Rep Power
    5

    Default Re: Graphics smearing in JFrame

    Excuse me, but what exactly are you trying to do? Why all the timing stuff and stop/start? And above all you should never (or extremely rarely if at all) use the Graphics context yourself. It should only be called via paintComponent (which means you should not be paintinng on the JFrame but a JPanel).

    Regards,
    Jim
    The Java™ Tutorial | SSCCE | Java Naming Conventions
    Poor planning our your part does not constitute an emergency on my part.

  6. #6
    ImTroyMiller is offline Member
    Join Date
    Jan 2014
    Posts
    20
    Rep Power
    0

    Default Re: Graphics smearing in JFrame

    This is for a game that may have animations.

  7. #7
    gimbal2 is offline Just a guy
    Join Date
    Jun 2013
    Location
    Netherlands
    Posts
    3,900
    Rep Power
    5

    Default Re: Graphics smearing in JFrame

    Quote Originally Posted by ImTroyMiller View Post
    It did exactly what I wanted, but it's very slow and flickering. In addition, I think the keys weren't working as well.
    Yes we'll you're applying Swing (a high level GUI toolkit), but then you go ahead and manually meddle anyway basically bypassing and working against the framework itself; it is not really a big surprise that things don't work well.

    If you want to use Swing, use Swing 100%; do custom painting in a JPanel and use a Swing timer to manage your game loop and trigger proper repaints so Swing remains the one in charge; that way you'll be going through Swing's built in double painting mechanism too (which is a mechanism to prevent flickering artifacts) and you won't be trying to fight for the right to party with it.

    If you don't want to apply Swing then ditch it entirely and use a Window, a Canvas and a BufferStrategy which is the most minimal you can get in Java2D land.
    "Syntactic sugar causes cancer of the semicolon." -- Alan Perlis

  8. #8
    jim829 is offline Senior Member
    Join Date
    Jan 2013
    Location
    Northern Virginia, United States
    Posts
    3,534
    Rep Power
    5

    Default Re: Graphics smearing in JFrame

    That's fine. But you're going about it incorrectly. You really should read Lesson: Performing Custom Painting (The Java™ Tutorials > Creating a GUI With JFC/Swing) if you are planning on doing painting.

    Regards,
    Jim
    The Java™ Tutorial | SSCCE | Java Naming Conventions
    Poor planning our your part does not constitute an emergency on my part.

  9. #9
    ImTroyMiller is offline Member
    Join Date
    Jan 2014
    Posts
    20
    Rep Power
    0

    Default Re: Graphics smearing in JFrame

    I'm just going to stick with Slick2D for now. Adventually I'll port it to Libgdx for a mobile app.

  10. #10
    gimbal2 is offline Just a guy
    Join Date
    Jun 2013
    Location
    Netherlands
    Posts
    3,900
    Rep Power
    5

    Default Re: Graphics smearing in JFrame

    Good choice!
    "Syntactic sugar causes cancer of the semicolon." -- Alan Perlis

Similar Threads

  1. Displaying graphics on JFrame
    By ManyProblems in forum New To Java
    Replies: 5
    Last Post: 07-31-2012, 06:12 AM
  2. Question on Graphics/JFrame/KeyEvents
    By loopsnhoops in forum New To Java
    Replies: 4
    Last Post: 02-10-2011, 11:22 PM
  3. Need Help with graphics / Jframe
    By loopsnhoops in forum AWT / Swing
    Replies: 1
    Last Post: 02-10-2011, 11:15 PM
  4. problem with jframe&jmenu&graphics
    By beni.vd in forum AWT / Swing
    Replies: 1
    Last Post: 12-31-2010, 07:07 PM
  5. Graphics with JFrame
    By kandt in forum New To Java
    Replies: 3
    Last Post: 12-02-2008, 12:51 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •