JTextArea font/character count issue
Hi everyone! This is my first post to this forum and I would like to say first that I am glad to be part of a Java community. I have been working for some time on making my own toy virtual machine in Java but I have run into a problem. I want it to be a virtual machine with a virtual console with 80 characters by 25 characters (this number is flexible and not that important) but I can't figure out how to leverage a JTextArea to my advantage here. My question I suppose is this. First, how can I use a JTextArea to keep these dimensions and second how can I adjust the font size to automatically keep these constraints when the JTextArea is resized? I am not opposed to writing my own layout or even using absolute positioning if necessary since this is only for my use at this point so any pointers would be appreciated. Thanks everyone!
Re: JTextArea font/character count issue
To detect when your JTextArea is resized, you can use a ComponentListener (doc here), particularly the componentResized() method to detect when the JTextArea is resized.
After that, I'd suggest looking at Fonts (doc) and finding a way to calculate how a font size relates to pixels in height and average width.
Re: JTextArea font/character count issue
Did you try the constructor that specifies the number of rows and columns? You can use this (as well as the corresponding setRows/Columns methods) to define the width/height in characters.
Re: JTextArea font/character count issue
Thanks guys for your replies! Yes I have used the constructor that specifies columns and rows but that doesn't work right because of the font size I guess. When I set it to 20, 50 I get about eighty odd characters across and 30 down. As for setting the point size based on my window size I have tried to compute the size of the font like that but it gives me fits sometimes. I can't remember the formula I was using for font size but when I find it again I will post the formula and see if anyone else can give me an idea of an appropriate method to set the size given the size of the text area. Thanks for the advice about the ComponentListener though, I will try that!
Re: JTextArea font/character count issue
To get information about Font sizes (height and width, etc.), the FontMetrics class is quite useful. For your purposes, I'd look at getHeight() and charWidth().
Note that FontMetrics is abstract, meaning you cannot instantiate it, but no worries: every Graphics object has one. So, to get the FontMetrics of a JTextArea, do this:
<JTextArea>.getGraphics().getFontMetrics();
Where <JTextArea> is any instance of JTextArea.
Re: JTextArea font/character count issue
So. I'm back :D I wrote some code based on FontMetrics and trying to resize the font to provide an exact size for 80*25 characters but I have to say I am terrible at math. Here is the code I have so far for my window:
Code Java:
import java.awt.Component;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class MachineInterface extends JFrame implements ComponentListener {
// member variables
private JTextArea machineConsole;
private JScrollPane consolePane;
private JButton startButton;
GridBagLayout winLayout;
GridBagConstraints gbc;
// public MachineInterface () constructor method
public MachineInterface () {
// initialize the layout
winLayout = new GridBagLayout ();
gbc = new GridBagConstraints ();
this.setLayout (winLayout);
// initialize the controls
machineConsole = new JTextArea ();
consolePane = new JScrollPane (machineConsole);
startButton = new JButton ("Start Machine");
// add the controls to the window
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1.0;
gbc.weighty = 3.0;
addComponent (consolePane, 1, 1, 4, 3);
gbc.weighty = 1.0;
gbc.fill = GridBagConstraints.NONE;
addComponent (startButton, 1, 4, 1, 1);
// set up font for console window
machineConsole.setFont(new Font ("Courier New", Font.PLAIN, 10));
machineConsole.setLineWrap (true);
machineConsole.addComponentListener (this);
// open the window and set everything up
this.setSize (400, 300);
this.setDefaultCloseOperation (EXIT_ON_CLOSE);
this.setVisible (true);
}
// add a control to the window using the GridBagConstraints
public void addComponent (Component c, int x, int y, int width, int height) {
gbc.gridx = x;
gbc.gridy = y;
gbc.gridwidth = width;
gbc.gridheight = height;
winLayout.setConstraints (c, gbc);
this.add (c);
}
// compute font size based on window height and width
public void adjustFontForResolution (JTextArea toAdjust) {
// get the dimensions of the JTextArea
int width = toAdjust.getWidth ();
int height = toAdjust.getHeight ();
float desiredWidth = width / 100;
float desiredHeight = height / 25;
System.out.println ("Width: " + width + ", Height: " + height);
// determine the font metrics that we need and construct a font object to use
FontMetrics currentMetrics = toAdjust.getGraphics().getFontMetrics();
float ptSize = toAdjust.getGraphics().getFont().getSize2D();
int fontWidth = currentMetrics.charWidth('f');
// find the width of one point font
float ptOneWidth = fontWidth / ptSize;
float newWidth = ptOneWidth;
float newPts = 1.0f;
while (newWidth < desiredWidth) {
newWidth += ptOneWidth;
newPts++;
}
System.out.println ("New point size: " + newPts);
toAdjust.setFont(this.getGraphics().getFont().deriveFont(newPts));
}
// component listener implementations
public void componentShown (ComponentEvent e) { }
public void componentHidden (ComponentEvent e) { }
public void componentMoved (ComponentEvent e) { }
// when the window is resized we have to recompute
// the font size for the console
public void componentResized (ComponentEvent e) {
// get the pixel size of the JTextArea and resize
// the font based on that size
adjustFontForResolution (this.machineConsole);
}
// main method
public static void main (String [] args) {
new MachineInterface ();
}
}
This is the entire class for my GUI so I figured I would just post it. I'm sorry if that is too big. Please note the code within the method adjustFontForResolution as this is the code that I have written to handle resizing. I can't seem to get the math right does anyone have an example of how I may be able to do this? I'm sorry I am SERIOUSLY bad with forming equations!
Re: JTextArea font/character count issue
From my experience, small little hacks like this might work in the short term but make maintenance a nightmare in the long term, especially when there are ways to get what you need using the API. The setRows and setColumns methods are there for a reason (similar to setting them in the constructor). You need to a) set these after you have set the font you wish to use and b) Use the appropriate layout and set the appropriate preferred size of the parent containers (for instance, wrap your JScrollPane in a JPanel that has a FlowLayout and add this). I don't fully know what your desired goal is, but I would recommend playing a bit more with wrapped layouts and studying the API
Re: JTextArea font/character count issue
I actually discovered the setRows and setColumns having to be set AFTER font size thing earlier today with my font size. I completely eliminated window resizing and used pack () to make the window the correct size for the component. Everything is working exactly how I want it to now. Thanks all!