Reputation: 503
I'm trying to make a simple word processor where there is a ControlPanel on the top of the JFrame and a TextPanel in the center with a JTextArea component. A basic overview of my program is that there is one JPanel called MyPanel which takes up the entire JFrame and holds the rest of the panels. Inside MyPanel is ControlPanel and TextPanel (not nested). ControlPanel contains various JButtons and JComboBoxes for font styling while TextPanel simply has a JTextArea.
What I want is that when I press a JButton in the ControlPanel class, for example BOLD, it will go to actionPerformed() and do "text.repaint." But what I'm finding is that text.repaint does not even go to the TextPanel and never enters the paintComponent method. I tried nesting the ControlPanel in the TextPanel and giving it a BorderLayout.NORTH, and that works fine, but then it seems like the paper is connected to the control panel, which is something I don't like.
Can somebody give me an alternative or explain why text.repaint() is not working?
Here's the important portion of my code for reference: (important parts are marked with //)
NOTICE: class ControlPanel and class TextPanel aren't aligned because I was too lazy to fix the alignment on a mediocre text editor. Trust me, they are not nested and are both in the class MyPanel
class ControlPanel extends JPanel implements ActionListener
{
JButton bold, italics;
JComboBox font;
JComboBox size;
String [] fontsizes = {"8", "10", "12", "16", "20", "24", "36", "48", "56", "72"};
String [] fonttypes = {"Arial", "Serif", "Sans Serif", "Gothic", "Helvetica", "Times New Roman", "Comic Sans"};
public ControlPanel() // class ControlPanel control
{
setBackground(Color.gray);
this.setLayout(new FlowLayout());
Font boldfont = new Font("Serif", Font.BOLD, 16);
bold = new JButton("B");
bold.setFont(boldfont);
//bold.getModel().setPressed(true);
bold.addActionListener(this);
this.add(bold);
Font italicsfont = new Font("Serif", Font.ITALIC, 16);
italics = new JButton("I");
italics.setFont(italicsfont);
//italics.getModel().setPressed(true);
italics.addActionListener(this);
this.add(italics);
font = new JComboBox(fonttypes);
font.setSelectedIndex(0);
font.addActionListener(this);
this.add(font);
size = new JComboBox(fontsizes);
size.setSelectedIndex(2);
size.addActionListener(this);
size.setEditable(true);
this.add(size);
}
public void actionPerformed(ActionEvent e)
{
String command = e.getActionCommand();
if (command.equals("B"))
{
if (boldfont)
boldfont = false;
else
boldfont = true;
}
if (command.equals("I"))
{
if (italicsfont)
italicsfont = false;
else
italicsfont = true;
}
fontselection = (String)font.getSelectedItem();
sizeselection = Integer.parseInt((String)(size.getSelectedItem()));
text.repaint(); // repaints TextPanel text class
}
}
class TextPanel extends JPanel // class TextPanel text
{
JTextArea type;
public TextPanel()
{
this.setLayout(new BorderLayout());
type = new JTextArea();
type.setEditable(true);
type.setLineWrap(true);
type.setWrapStyleWord(true);
type.setTabSize(4);
type.setMargin(new Insets(80, 100, 80, 100));
this.add(type, BorderLayout.CENTER);
}
public void paintComponent(Graphics g) // paintComponent() method for TextPanel
{
System.out.println("paintComponent of text"); // does not print out in terminal
super.paintComponent(g);
Font regfont;
int fontstyle = 0;
regfont = new Font("Arial", Font.PLAIN, 12);
if (boldfont)
{
fontstyle = 1;
}
else if (!boldfont)
{
fontstyle = 0;
}
if (italicsfont)
{
if (boldfont)
fontstyle = 3;
else
fontstyle = 2;
}
else if (!italicsfont)
{
if (boldfont)
fontstyle = 1;
else
fontstyle = 0;
}
regfont = new Font(fontselection, fontstyle, sizeselection);
type.setFont(regfont);
}
}
Upvotes: 2
Views: 143
Reputation: 347204
Your paint
method adds no functionality to the overall application. You'd actually be better off allowing the control pane to pass state request to the TextPane
that then effect the text area directly.
Basically, what you're doing in the paintComponent
method is the wrong approach for what it is you are trying to and could, in fact, produce a cyclic repaint call scenario that could consume your CPU
Updated with example
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestTextPane01 {
public static void main(String[] args) {
new TestTextPane01();
}
public TestTextPane01() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
TextPanel textPanel = new TextPanel();
ControlPanel controlPanel = new ControlPanel(textPanel);
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(controlPanel, BorderLayout.NORTH);
frame.add(textPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
class ControlPanel extends JPanel implements ActionListener {
JButton bold, italics;
JComboBox font;
JComboBox size;
String[] fontsizes = {"8", "10", "12", "16", "20", "24", "36", "48", "56", "72"};
String[] fonttypes = {"Arial", "Serif", "Sans Serif", "Gothic", "Helvetica", "Times New Roman", "Comic Sans"};
private boolean boldfont;
private boolean italicsfont;
private String fontselection;
private int sizeselection;
private TextPanel textPane;
public ControlPanel(TextPanel txtPanel) // class ControlPanel control
{
textPane = txtPanel;
setBackground(Color.gray);
this.setLayout(new FlowLayout());
Font boldfont = new Font("Serif", Font.BOLD, 16);
bold = new JButton("B");
bold.setFont(boldfont);
//bold.getModel().setPressed(true);
bold.addActionListener(this);
this.add(bold);
Font italicsfont = new Font("Serif", Font.ITALIC, 16);
italics = new JButton("I");
italics.setFont(italicsfont);
//italics.getModel().setPressed(true);
italics.addActionListener(this);
this.add(italics);
font = new JComboBox(fonttypes);
font.setSelectedIndex(0);
font.addActionListener(this);
this.add(font);
size = new JComboBox(fontsizes);
size.setSelectedIndex(2);
size.addActionListener(this);
size.setEditable(true);
this.add(size);
}
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if (command.equals("B")) {
boldfont = !boldfont;
} else if (command.equals("I")) {
italicsfont = !italicsfont;
}
fontselection = (String) font.getSelectedItem();
sizeselection = Integer.parseInt((String) (size.getSelectedItem()));
// text.repaint(); // repaints TextPanel text class
textPane.setFont(boldfont, italicsfont);
}
}
class TextPanel extends JPanel // class TextPanel text
{
JTextArea type;
public TextPanel() {
this.setLayout(new BorderLayout());
type = new JTextArea();
type.setEditable(true);
type.setLineWrap(true);
type.setWrapStyleWord(true);
type.setTabSize(4);
type.setMargin(new Insets(80, 100, 80, 100));
this.add(type, BorderLayout.CENTER);
}
public void setFont(boolean boldFont, boolean italicsFont) {
Font font = type.getFont();
int style = Font.PLAIN;
if (boldFont && italicsFont) {
style = Font.BOLD | Font.ITALIC;
} else if (boldFont) {
style = Font.BOLD;
} else if (italicsFont) {
style = Font.ITALIC;
}
font = font.deriveFont(style);
System.out.println("Font");
type.setFont(font);
}
}
}
I'd also suggest you have a read of How to Use Scroll Panes, Performing Custom Painting and Painting in AWT and Swing
Upvotes: 2