Java and Swing with a game loop
===

(Not so) short question here. I am working on making a simple roguelike using Swing as the UI rather than the console (Which makes it easier to work with in Eclipse, among other things) but I seem to have hit a roadblock.

What I am having trouble with is that when I enter the game loop, the UI will not display properly. I get an ugly window frame that gives me the 'solitaire' effect during the entire thing and while running it quickly grows in RAM usage. 

Am I missing something critical about Swing here? Is it mandatory that I use Swing's concurrency setup to do this? If so, what would be the best approach?

The full code is below:

	package roguelike;

	import java.awt.Color;
	import java.awt.Dimension;
	import java.awt.Font;
	import java.awt.FontMetrics;
	import java.awt.event.KeyEvent;
	import java.awt.event.KeyListener;
	import java.util.LinkedList;

	import javax.swing.*;
	import javax.swing.text.*;

	public class roguelike {
		Color c_black = new Color(0x000000);
		Color c_white = new Color(0xffffff);
		Color c_red = new Color(0xff0000);
		Color c_blue = new Color(0x0000ff);
		Color c_green = new Color(0x00ff00);
		
		UI ui = null;
		Player me = null;
		Map gamemap = null;
		LinkedList<Character> keyqueue = new LinkedList<Character>();
		
		int charheight = 20;
		int charwidth = 80;
		
		public static void main(String[] args){
			SwingUtilities.invokeLater(new Runnable(){
				public void run(){
					roguelike game = new roguelike();
					game.run();
				}
			});
		}
		public roguelike(){
			gamemap = new Map();
			ui = new UI(charheight,charwidth,"Monospaced");
			me = new Player();
		}
		private class UI extends JFrame implements KeyListener{
			private static final long serialVersionUID = 9065411532125953842L;
			JPanel disp_screen = null;
			JTextPane disp_screen_text = null;
			StyledDocument disp_doc = null;
			Font mono_norm = null;
			int pxheight = 0;
			int pxwidth = 0;
			String[][] ctemp = new String[charheight][charwidth];
			String[][] stemp = new String[charheight][charwidth];
			
			
			public UI(int h,int w,String fontname){
				setVisible(true);
				charheight = h;
				charwidth = w;
				addKeyListener(this);
				
				this.setResizable(false);
				mono_norm = new Font(fontname,0,25);
				initScreen(h,w);
				add(disp_screen);
				makeStyles();
				try {
					disp_doc.insertString(0, "12345678901234567890123456789012345678901234567890123456789012345678901234567890\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20", disp_doc.getStyle("Default"));
				} catch (BadLocationException e) {
					e.printStackTrace();
				}
				
				Dimension temp = disp_screen.getSize();
				this.setSize(temp);
				this.setDefaultCloseOperation(EXIT_ON_CLOSE);			
				

				pack();
				try {
					disp_doc.remove(0, disp_doc.getLength());
				} catch (BadLocationException e) {
					e.printStackTrace();
				}
				renderMap(gamemap.getText(),gamemap.getStyles());

			}
			@Override
			public void keyPressed(KeyEvent e) {
				// TODO Auto-generated method stub
				
			}
			@Override
			public void keyReleased(KeyEvent e) {
				// TODO Auto-generated method stub
				
			}
			@Override
			public void keyTyped(KeyEvent e) {
				keyqueue.add(e.getKeyChar());
			}
			private void initScreen(int height, int width){
				FontMetrics metric = getFontMetrics(mono_norm);
				String temp = null;
				
				//generate a string of the right width from which to grab metrics
				for(int x=0;x<=width;x++){
					temp += '.';
				}
				pxwidth = SwingUtilities.computeStringWidth(metric, temp);
				pxheight = (metric.getHeight())*charheight;
				
				disp_screen = new JPanel();
				disp_screen_text = new JTextPane();
				disp_screen_text.setEditable(false);
				disp_screen_text.setAlignmentX(LEFT_ALIGNMENT);
				disp_screen_text.setAlignmentY(TOP_ALIGNMENT);
				disp_screen_text.setFont(mono_norm);
				disp_screen_text.setBackground(c_black);
				disp_screen_text.setForeground(c_green);
				disp_doc = disp_screen_text.getStyledDocument();
				
				
				disp_screen.add(disp_screen_text);
				disp_screen.setAlignmentX(LEFT_ALIGNMENT);
				disp_screen.setAlignmentY(TOP_ALIGNMENT);
				disp_screen.setLayout(new BoxLayout(disp_screen,BoxLayout.Y_AXIS));
			}
			private void makeStyles(){
				//The default style removes all special formatting and returns the text to standard nonsense
				Style sty_default = disp_doc.addStyle("Default", null);
				StyleConstants.setFontFamily(sty_default, "Monospaced");
				StyleConstants.setFontSize(sty_default, 18);
				StyleConstants.setForeground(sty_default, c_green);
				StyleConstants.setBackground(sty_default, c_black);
				StyleConstants.setItalic(sty_default, false);
				StyleConstants.setBold(sty_default, false);
				//StyleConstants.setSpaceAbove(sty_default, 0);
				//StyleConstants.setSpaceBelow(sty_default, 0);
				
				//The following styles apply certain effects. They are meant to be set without replacing styles
				Style sty_bold = disp_doc.addStyle("Bold", disp_doc.getStyle("Default"));
				StyleConstants.setBold(sty_bold,true);
				
				Style sty_ital = disp_doc.addStyle("Italic", disp_doc.getStyle("Default"));
				StyleConstants.setItalic(sty_ital, true);
				
			}
			private void clearMap(){
				try {
					disp_doc.remove(0, disp_doc.getLength());
				} catch (BadLocationException e1) {
					e1.printStackTrace();
				}
				try {
					//CLEAR THE MAP
					//For every row...
					for(int y=0;y<charheight;y++){
						//For every column location in a row...
						for(int x=0;x<charwidth;x++){
							disp_doc.insertString(disp_doc.getLength(),".", disp_doc.getStyle("Default"));
						}
						disp_doc.insertString(disp_doc.getLength(),"\n", disp_doc.getStyle("Default"));
					}
				} catch (BadLocationException e){
						e.printStackTrace();
				}
			}
			public void renderMap(String[][] chars, String[][] styles){
				System.out.print("Rendering map...");
				clearMap();
				ctemp = chars;
				stemp = styles;
				
				try {
				
					//For every row...
					for(int y=0;y<charheight;y++){
						//For every column location in a row...
						for(int x=0;x<charwidth;x++){
							if(ctemp[y][x] != null){
								if(stemp[y][x] == "D"){
									disp_doc.remove((y*charwidth)+x, 1);
									disp_doc.insertString((y*charwidth)+x,ctemp[y][x], disp_doc.getStyle("Default"));
								} else if(stemp[y][x] == "B"){
									disp_doc.remove((y*charwidth)+x, 1);
									disp_doc.insertString((y*charwidth)+x,ctemp[y][x], disp_doc.getStyle("Bold"));
								} else if(stemp[y][x] == "I"){
									disp_doc.remove((y*charwidth)+x, 1);
									disp_doc.insertString((y*charwidth)+x,ctemp[y][x], disp_doc.getStyle("Italic"));
								} else{
									disp_doc.remove((y*charwidth)+x, 1);
									disp_doc.insertString((y*charwidth)+x,ctemp[y][x], disp_doc.getStyle("Default"));
								}
							}
						}
					}
				} catch (BadLocationException e){
					e.printStackTrace();
					System.err.print(e.getCause());
				}
			}
		}
		
		//Handles the virtualized information of characters on the map. Does NOT handle display of map on screen
		//Displaying the screen happens by passing required data to the ui member
		private class Map{
			//Holds an array of map characters
			String[][] text = new String[charheight][charwidth];
			//Holds an array of styles associated with each map character
			String[][] styles = new String[charheight][charwidth];
			
			
			public Map(){
			}
			public String[][] getText(){
				
				return text;
			}
			public String[][] getStyles(){
				return styles;
			}
			public void putch(String thing, String styledef,int y, int x){
				text[y][x] = thing;
				styles[y][x] = styledef;
			}
		}
		
		private class Player{
			//Player location, [y][x]
			int[] location = {0,0};
			String sym = "@";
			public Player(){
			}
			public int[] getLocation(){
				return location;
			}
			public String getSymbol(){
				return sym;
			}
			public void setLocation(int y, int x){
				location[0]=y;
				location[1]=x;
			}
			public void setSymbol(String newsym){
				sym = newsym;
			}
			public void move(int dir){
				//Movement will be handled in an 8 directional fashion
				//North is 1, like below
				//     812
				//     703
				//     654
				//////////////////////
				switch(dir){
					case 0:
						break;
					case 1:
						location[0] += 1;
						break;
					case 2:
						location[0] += 1;
						location[1] += 1;
						break;
					case 3:
						location[1] += 1;
						break;
					case 4:
						location[0] -= 1;
						location[1] += 1;
						break;
					case 5:
						location[0] -= 1;
						break;
					case 6:
						location[0] -= 1;
						location[1] -= 1;
						break;
					case 7:
						location[1] -= 1;
						break;
					case 8:
						location[0] += 1;
						location[1] -= 1;
					default:
						System.err.print("ERROR! "+dir+" is not a valid direction!");
						break;
				}
			}
		}

		/////////////////////////////////////////////////////
		/////////////FUNCTIONS///////////////////////////////
		/////////////////////////////////////////////////////
		public void run(){
			boolean running = true;
			while(running){
				//Render Map
				gamemap.putch(me.getSymbol(), "D", me.getLocation()[0], me.getLocation()[1]);
				ui.renderMap(gamemap.getText(), gamemap.getStyles());
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				//Wait for player input
				if(keyqueue.isEmpty()){
					continue;
				}
				//Act on input
				else{
					char input = keyqueue.getFirst();
					keyqueue.removeFirst();
					if(input == 'w'){
						me.move(1);
					}
					if(input =='a'){
						me.move(7);
					}
					if(input == 's'){
						me.move(5);
					}
					if(input == 'd'){
						me.move(3);
					}
				}
			}

		}
	}