Java Swing Leaning by Code
Java Swing Leaning by Code
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
setTitle()
method.
setSize(300, 200);
This code will resize the window to be 300 px wide and 200 px
tall.
setLocationRelativeTo(null);
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
SimpleExample ex = new SimpleExample();
ex.setVisible(true);
}
});
Quit button
In our next example, we will have a button. When we click on
the button, the application terminates.
package com.zetcode;
import
import
import
import
import
import
import
import
java.awt.Container;
java.awt.EventQueue;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
javax.swing.GroupLayout;
javax.swing.JButton;
javax.swing.JComponent;
javax.swing.JFrame;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
private void initUI() {
JButton quitButton = new JButton("Quit");
quitButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
System.exit(0);
}
});
createLayout(quitButton);
setTitle("Quit button");
setSize(300, 200);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private void createLayout(JComponent... arg) {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
gl.setAutoCreateContainerGaps(true);
gl.setHorizontalGroup(gl.createSequentialGroup()
.addComponent(arg[0])
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addComponent(arg[0])
);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
QuitButtonEx ex = new QuitButtonEx();
ex.setVisible(true);
}
});
}
}
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
JButton quitButton = new JButton("Quit");
We
plug
an
action
listener
to
the
button.
The
listener's actionPerformed() method will be called when we click on
the button. The action terminates the application by calling
the System.exit() method.
createLayout(quitButton);
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
gl.setVerticalGroup(gl.createSequentialGroup()
.addComponent(quitButton)
);
A tooltip
Tooltips are part of the internal application's help system. Swing
shows a small window if we hover a mouse pointer over an
object that has a tooltip set.
package com.zetcode;
import java.awt.EventQueue;
import javax.swing.GroupLayout;
import javax.swing.JButton;
6
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class TooltipEx extends JFrame {
public TooltipEx() {
initUI();
}
private void initUI() {
JButton btn = new JButton("Button");
btn.setToolTipText("A button component");
createLayout(btn);
setTitle("Tooltip");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private void createLayout(JComponent... arg) {
JPanel pane = (JPanel) getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
pane.setToolTipText("Content pane");
gl.setAutoCreateContainerGaps(true);
gl.setHorizontalGroup(gl.createSequentialGroup()
.addComponent(arg[0])
.addGap(200)
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addComponent(arg[0])
.addGap(120)
);
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
7
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
TooltipEx ex = new TooltipEx();
ex.setVisible(true);
}
});
}
}
In the example, we set a tooltip for the frame and the button.
btn.setToolTipText("A button component");
setTooltipText()
method.
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
too. Our window will display the button and the spaces that we
have set with the addGap() method.
Figure: Tooltip
Mnemonics
Mnemonics are shortcut keys that activate a component that
supports mnemonics. For instance, they can be used with
labels, buttons, or menu items.
package com.zetcode;
import
import
import
import
import
import
import
import
import
java.awt.Container;
java.awt.EventQueue;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
java.awt.event.KeyEvent;
javax.swing.GroupLayout;
javax.swing.JButton;
javax.swing.JComponent;
javax.swing.JFrame;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
System.out.println("Button pressed");
}
});
btn.setMnemonic(KeyEvent.VK_B);
createLayout(btn);
setTitle("Mnemonics");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private void createLayout(JComponent... arg) {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
gl.setAutoCreateContainerGaps(true);
gl.setHorizontalGroup(gl.createSequentialGroup()
.addComponent(arg[0])
.addGap(200)
);
gl.setVerticalGroup(gl.createParallelGroup()
.addComponent(arg[0])
.addGap(200)
);
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
MnemonicEx ex = new MnemonicEx();
ex.setVisible(true);
}
});
}
}
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
btn.setMnemonic(KeyEvent.VK_B);
Simple menu
We begin with a simple menubar example.
11
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
package com.zetcode;
import
import
import
import
java.awt.EventQueue;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
java.awt.event.KeyEvent;
import
import
import
import
import
javax.swing.ImageIcon;
javax.swing.JFrame;
javax.swing.JMenu;
javax.swing.JMenuBar;
javax.swing.JMenuItem;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Our example will show a menu with one item. Selecting the exit
menu item we close the application.
JMenuBar menubar = new JMenuBar();
JMenuBar
class.
A menu object is created with the JMenu class. The menus can
be accessed via keyboard as well. To bind a menu to a
particular key, we use the setMnemonic() method. In our case, the
menu can be opened with the Alt+F shortcut.
JMenuItem eMenuItem = new JMenuItem("Exit", icon);
eMenuItem.setMnemonic(KeyEvent.VK_E);
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
public void actionPerformed(ActionEvent event) {
System.exit(0);
}
});
file.add(eMenuItem);
menubar.add(file);
The menu item is added to the menu object and the menu
object is inserted into the menubar.
setJMenuBar(menubar);
sets
the
menubar
for
Submenu
Each menu can also have a submenu. This way we can put
similar commands into groups. For example we can place
commands that hide and show various toolbars like personal
bar, address bar, status bar or navigation bar into a submenu
called toolbars. Within a menu, we can separate commands
with a separator. The separator is a simple line. It is common
practice to separate commands like new, open, save from
commands like print, print preview with a single separator. In
addition to mnemonics, menu commands can be launched via
accelerators.
14
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
package com.zetcode;
import
import
import
import
import
import
import
import
java.awt.EventQueue;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
javax.swing.ImageIcon;
javax.swing.JFrame;
javax.swing.JMenu;
javax.swing.JMenuBar;
javax.swing.JMenuItem;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
16
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
A
tooltip
is
set
to
the setToolTipText() method.
the
Exit
menu
item
with
Figure: Submenu
17
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
import
import
import
import
import
import
import
import
import
import
import
import
import
import
java.awt.EventQueue;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
java.awt.event.KeyEvent;
javax.swing.AbstractAction;
static javax.swing.Action.MNEMONIC_KEY;
static javax.swing.Action.SMALL_ICON;
javax.swing.ImageIcon;
javax.swing.JFrame;
static javax.swing.JFrame.EXIT_ON_CLOSE;
javax.swing.JMenu;
javax.swing.JMenuBar;
javax.swing.JMenuItem;
javax.swing.KeyStroke;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
KeyEvent.VK_S));
JMenuItem exitMi = new JMenuItem("Exit", iconExit);
exitMi.setMnemonic(KeyEvent.VK_E);
exitMi.setToolTipText("Exit application");
exitMi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W,
ActionEvent.CTRL_MASK));
exitMi.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
System.exit(0);
}
});
fileMenu.add(newMi);
fileMenu.add(openMi);
fileMenu.add(saveMi);
fileMenu.addSeparator();
fileMenu.add(exitMi);
menubar.add(fileMenu);
setJMenuBar(menubar);
}
private class MenuItemAction extends AbstractAction {
public MenuItemAction(String text, ImageIcon icon,
Integer mnemonic) {
super(text);
putValue(SMALL_ICON, icon);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
System.out.println(e.getActionCommand());
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
ShortCutsEx ex = new ShortCutsEx();
ex.setVisible(true);
}
});
19
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
}
}
The Exit menu item does not use the action object. Its
functionality is built separately. We call the setMnemonic() method
to set a mnemonic key. To use a mnemonic, the component
must be visible on the screen. So we must first activate the
menu object, which makes the Exit menu item visible, and then
we can activate this menu item. This means that this menu
item is activated by the Alt+F+E key combination.
exitMi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W,
ActionEvent.CTRL_MASK));
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
super(text);
putValue(SMALL_ICON, icon);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
System.out.println(e.getActionCommand());
}
}
Figure:
Mnemonics and
accelerators
Mnemonics are visually hinted by underlined characters, the
accelerators have their shortcut keys shown next to the menu
item's label.
JCheckBoxMenuItem
A JCheckBoxMenuItem is a menu item that can be selected or
deselected. If selected, the menu item typically appears with a
checkmark next to it. If unselected or deselected, the menu
item appears without a checkmark. Like a regular menu item, a
21
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
check box menu item can have either text or a graphic icon
associated with it, or both.
package com.zetcode;
import
import
import
import
import
import
import
import
import
import
import
java.awt.BorderLayout;
java.awt.EventQueue;
java.awt.event.ItemEvent;
java.awt.event.ItemListener;
java.awt.event.KeyEvent;
javax.swing.BorderFactory;
javax.swing.JCheckBoxMenuItem;
javax.swing.JFrame;
javax.swing.JLabel;
javax.swing.JMenu;
javax.swing.JMenuBar;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
sbarMi.setSelected(true);
sbarMi.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
statusbar.setVisible(true);
} else {
statusbar.setVisible(false);
}
}
});
viewMenu.add(sbarMi);
menubar.add(fileMenu);
menubar.add(viewMenu);
setJMenuBar(menubar);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
CheckBoxMenuItemEx ex = new CheckBoxMenuItemEx();
ex.setVisible(true);
}
});
}
}
JCheckBoxMenuItem
put
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
sbarMi.setDisplayedMnemonicIndex(5);
sbarMi.setSelected(true);
Because
the
statusbar
is initially
visible,
the JCheckBoxMenuItem's setSelected() method to select it.
we
call
sbarMi.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
statusbar.setVisible(true);
} else {
statusbar.setVisible(false);
}
}
});
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
java.awt.EventQueue;
javax.swing.Box;
javax.swing.JFrame;
javax.swing.JMenu;
javax.swing.JMenuBar;
menubar.add(fileMenu);
menubar.add(viewMenu);
menubar.add(toolsMenu);
menubar.add(Box.createHorizontalGlue());
menubar.add(helpMenu);
setJMenuBar(menubar);
}
public static void main(String[] args) {
25
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
RightMenuEx ex = new RightMenuEx();
ex.setVisible(true);
}
});
}
}
The example shows three menus on the left and one menu on
the right.
JMenuBar menubar = new JMenuBar();
JMenu
JMenu
JMenu
JMenu
A popup menu
26
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
java.awt.EventQueue;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
java.awt.event.MouseAdapter;
java.awt.event.MouseEvent;
javax.swing.JFrame;
javax.swing.JMenuItem;
javax.swing.JPopupMenu;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
setExtendedState(JFrame.MAXIMIZED_BOTH);
}
}
});
pmenu.add(maxMi);
JMenuItem quitMi = new JMenuItem("Quit");
quitMi.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
pmenu.add(quitMi);
addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON3) {
pmenu.show(e.getComponent(), e.getX(), e.getY());
}
}
});
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
PopupMenuEx pm = new PopupMenuEx();
pm.setVisible(true);
}
});
}
}
28
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
JPopupMenu
29
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
JToolbar
Menus group commands that we can use in an application.
Toolbars provide a quick access to the most frequently used
commands. In Java Swing, the JToolBar class creates a toolbar in
an application.
package com.zetcode;
import
import
import
import
import
import
import
import
import
import
java.awt.BorderLayout;
java.awt.EventQueue;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
javax.swing.ImageIcon;
javax.swing.JButton;
javax.swing.JFrame;
javax.swing.JMenu;
javax.swing.JMenuBar;
javax.swing.JToolBar;
30
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
setTitle("Simple toolbar");
setSize(300, 200);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private void createMenuBar() {
JMenuBar menubar = new JMenuBar();
JMenu file = new JMenu("File");
menubar.add(file);
setJMenuBar(menubar);
}
private void createToolBar() {
JToolBar toolbar = new JToolBar();
ImageIcon icon = new ImageIcon("exit.png");
JButton exitButton = new JButton(icon);
toolbar.add(exitButton);
exitButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
System.exit(0);
}
});
add(toolbar, BorderLayout.NORTH);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
ToolbarEx ex = new ToolbarEx();
ex.setVisible(true);
}
});
}
}
JToolBar.
31
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
JButton exitButton = new JButton(icon);
toolbar.add(exitButton);
BorderLayout.
Toolbars
Often more than one toolbar is displayed on the window.
package com.zetcode;
import
import
import
import
import
import
import
import
import
import
java.awt.Container;
java.awt.EventQueue;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
javax.swing.GroupLayout;
javax.swing.ImageIcon;
javax.swing.JButton;
javax.swing.JComponent;
javax.swing.JFrame;
javax.swing.JToolBar;
32
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
createToolBars();
setTitle("Toolbars");
setSize(360, 250);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private void createToolBars() {
JToolBar toolbar1 = new JToolBar();
JToolBar toolbar2 = new JToolBar();
ImageIcon
ImageIcon
ImageIcon
ImageIcon
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
gl.setVerticalGroup(gl.createSequentialGroup()
.addComponent(arg[0])
.addComponent(arg[1])
);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
ToolbarsEx ex = new ToolbarsEx();
ex.setVisible(true);
}
});
}
}
34
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Figure: Toolbars
In this part of the Java Swing tutorial, we have mentioned
menus and toolbars.
++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++Lesson 3:
No manager
It is possible to go without a layout manager. There might be
situations where we might not need a layout manager. But in
35
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
we
position
components
package zetcode;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class AbsoluteExample extends JFrame {
public AbsoluteExample() {
initUI();
}
public final void initUI() {
setLayout(null);
JButton ok = new JButton("OK");
ok.setBounds(50, 50, 80, 25);
JButton close = new JButton("Close");
close.setBounds(150, 50, 80, 25);
add(ok);
add(close);
setTitle("Absolute positioning");
setSize(300, 250);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
AbsoluteExample ex = new AbsoluteExample();
ex.setVisible(true);
}
});
}
}
36
using
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
We
the
use
absolute
setLayout() method.
positioning
by
providing
null
to
FlowLayout manager
This is the simplest layout manager in the Java Swing toolkit. It
is mainly used in combination with other layout managers.
When calculating its children size, a flow layout lets each
component assume its natural (preferred) size.
The manager puts components into a row. In the order, they
were added. If they do not fit into one row, they go into the
next one. The components can be added from the right to the
left or vice versa. The manager allows to align the components.
Implicitly, the components are centered and there is 5px space
among components and components and the edges of the
container.
FlowLayout()
FlowLayout(int align)
FlowLayout(int align, int hgap, int vgap)
37
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
import
import
import
import
import
javax.swing.JFrame;
javax.swing.JPanel;
javax.swing.JTextArea;
javax.swing.JTree;
javax.swing.SwingUtilities;
38
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
GridLayout
The GridLayout layout manager lays out components in a
rectangular grid. The container is divided into equally sized
rectangles. One component is placed in each rectangle.
package zetcode;
import java.awt.GridLayout;
39
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
import
import
import
import
import
import
javax.swing.BorderFactory;
javax.swing.JButton;
javax.swing.JFrame;
javax.swing.JLabel;
javax.swing.JPanel;
javax.swing.SwingUtilities;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
}
}
Here we set the grid layout manager for the panel component.
The layout manager takes four parameters. The number of
rows, the number of columns and the horizontal and vertical
gaps between components.
BorderLayout
A BorderLayout manager is a very handy layout manager. I
haven't seen it elsewhere. It divides the space into five regions.
North, West, South, East and Centre. Each region can have only
one component. If we need to put more components into a
region, we can simply put a panel there with a manager of our
choice. The components in N, W, S, E regions get
their preferred size. The component in the centre takes up the
whole space left.
41
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
It does not look good if child components are too close to each
other. We must put some space among them. Each component
in Swing toolkit can have borders around its edges. To create a
border, we either create a new instance of an EmptyBorder class
or we use a BorderFactory. Except for EmptyBorder, there are
other types of borders as well. But for layout management we
will use only this one.
package zetcode;
import
import
import
import
java.awt.BorderLayout;
java.awt.Color;
java.awt.Dimension;
java.awt.Insets;
import
import
import
import
javax.swing.JFrame;
javax.swing.JPanel;
javax.swing.SwingUtilities;
javax.swing.border.EmptyBorder;
42
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
BorderExample ex = new BorderExample();
ex.setVisible(true);
}
});
}
}
The example will display a gray panel and border around it.
JPanel panel = new JPanel(new BorderLayout());
JPanel top = new JPanel();
43
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
package zetcode;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Insets;
import
import
import
import
import
import
import
import
import
import
import
javax.swing.ImageIcon;
javax.swing.JButton;
javax.swing.JFrame;
javax.swing.JLabel;
javax.swing.JMenu;
javax.swing.JMenuBar;
javax.swing.JTextArea;
javax.swing.JToolBar;
javax.swing.SwingUtilities;
javax.swing.border.EmptyBorder;
javax.swing.border.LineBorder;
44
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
JButton selectb = new JButton(select);
selectb.setBorder(new EmptyBorder(3, 0, 3, 0));
JButton freehandb = new JButton(freehand);
freehandb.setBorder(new EmptyBorder(3, 0, 3, 0));
JButton shapeedb = new JButton(shapeed);
shapeedb.setBorder(new EmptyBorder(3, 0, 3, 0));
vertical.add(selectb);
vertical.add(freehandb);
vertical.add(shapeedb);
add(vertical, BorderLayout.WEST);
add(new JTextArea(), BorderLayout.CENTER);
JLabel statusbar = new JLabel(" Statusbar");
statusbar.setPreferredSize(new Dimension(-1, 22));
statusbar.setBorder(LineBorder.createGrayLineBorder());
add(statusbar, BorderLayout.SOUTH);
setSize(350, 300);
setTitle("BorderLayout");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
BorderLayoutExample ex = new BorderLayoutExample();
ex.setVisible(true);
}
});
}
}
default
BorderLayout
layout
manager
for
a JFrame component
manager. So we don't have to set it.
add(toolbar, BorderLayout.NORTH);
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
BoxLayout
BoxLayout is a powerful manager that can be used to create
sofisticated layouts. This layout manager puts components into
a row or into a column. It enables nesting, a powerful feature
that makes this manager very flexible. It means that we can
put a box layout into another box layout.
The box layout manager is often used with the Box class. This
class creates several invisible components, which affect the
final layout.
glue
strut
rigid area
46
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Let's say we want to put two buttons into the right bottom
corner of the window. We will use the boxlayout managers to
accomplish this.
package zetcode;
import java.awt.Dimension;
import
import
import
import
import
import
javax.swing.Box;
javax.swing.BoxLayout;
javax.swing.JButton;
javax.swing.JFrame;
javax.swing.JPanel;
javax.swing.SwingUtilities;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
We will create two panels. The basic panel has a vertical box
layout. The bottom panel has a horizontal one. We will put a
bottom panel into the basic panel. We will right align the
bottom panel. The space between the top of the window and
the bottom panel is expandable. It is done by the vertical glue.
basic.setLayout(new BoxLayout(basic, BoxLayout.Y_AXIS));
BoxLayout.
48
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
We also put some space between the bottom panel and the
border of the window.
javax.swing.Box;
javax.swing.BoxLayout;
javax.swing.JButton;
javax.swing.JFrame;
javax.swing.JPanel;
javax.swing.SwingUtilities;
javax.swing.border.EmptyBorder;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
panel.add(Box.createRigidArea(new Dimension(0, 5)));
panel.add(new JButton("Button"));
panel.add(Box.createRigidArea(new Dimension(0, 5)));
panel.add(new JButton("Button"));
panel.add(Box.createRigidArea(new Dimension(0, 5)));
panel.add(new JButton("Button"));
add(panel);
pack();
setTitle("RigidArea");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
RigidAreaExample ex = new RigidAreaExample();
ex.setVisible(true);
}
});
}
}
We use a vertical
BoxLayout
panel.add(new JButton("Button"));
panel.add(Box.createRigidArea(new Dimension(0, 5)));
panel.add(new JButton("Button"));
50
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
import
import
import
import
java.awt.Color;
java.awt.Dimension;
java.awt.FlowLayout;
java.awt.event.KeyEvent;
import
import
import
import
import
import
import
import
import
import
import
javax.swing.BorderFactory;
javax.swing.BoxLayout;
javax.swing.ImageIcon;
javax.swing.JButton;
javax.swing.JCheckBox;
javax.swing.JDialog;
javax.swing.JLabel;
javax.swing.JPanel;
javax.swing.JSeparator;
javax.swing.JTextPane;
javax.swing.SwingUtilities;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
pane.setContentType("text/html");
String text = "<p><b>Closing windows using the mouse wheel</b></p>"
+
"<p>Clicking with the mouse wheel on an editor tab closes the window. "
+
"This method works also with dockable windows or Log window
tabs.</p>";
pane.setText(text);
pane.setEditable(false);
textPanel.add(pane);
basic.add(textPanel);
JPanel boxPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 20, 0));
JCheckBox box = new JCheckBox("Show Tips at startup");
box.setMnemonic(KeyEvent.VK_S);
boxPanel.add(box);
basic.add(boxPanel);
JPanel bottom = new JPanel(new FlowLayout(FlowLayout.RIGHT));
JButton ntip = new JButton("Next Tip");
ntip.setMnemonic(KeyEvent.VK_N);
JButton close = new JButton("Close");
close.setMnemonic(KeyEvent.VK_C);
bottom.add(ntip);
bottom.add(close);
basic.add(bottom);
bottom.setMaximumSize(new Dimension(450, 0));
setTitle("Tip of the Day");
setSize(new Dimension(450, 350));
setResizable(false);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
TipOfDayExample ex = new TipOfDayExample();
ex.setVisible(true);
}
});
}
53
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
}
54
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
edge of the dialog, the panel must stretch horizontally from the
beginning to the end.
++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++
Lesson 4:
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
event source
event object
event listener
The Event source is the object whose state changes. It
generates Events. The Event object (Event) encapsulates the
state changes in the event source. The Event listener is the
object that wants to be notified. Event source object delegates
the task of handling an event to the event listener.
Event handling in Java Swing toolkit is very powerful and
flexible. Java uses Event Delegation Model. We specify the
objects that are to be notified when a specific event occurs.
An event object
When something happens in the application, an event object is
created. For example, when we click on the button or select an
item from a list. There are several types of events,
including ActionEvent,TextEvent, FocusEvent, and ComponentEvent. Each
of them is created under specific conditions.
An event object holds information about an event that has
occurred. In the next example, we will analyse an ActionEvent in
more detail.
package com.zetcode;
import
import
import
import
import
import
import
import
import
import
import
java.awt.Container;
java.awt.Dimension;
java.awt.EventQueue;
java.awt.event.ActionEvent;
java.text.DateFormat;
java.util.Date;
java.util.Locale;
javax.swing.AbstractAction;
javax.swing.BorderFactory;
javax.swing.DefaultListModel;
javax.swing.GroupLayout;
56
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
import
import
import
import
javax.swing.JButton;
javax.swing.JFrame;
static javax.swing.JFrame.EXIT_ON_CLOSE;
javax.swing.JList;
57
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
@Override
public void actionPerformed(ActionEvent e) {
Locale locale = Locale.getDefault();
Date date = new Date(e.getWhen());
String tm = DateFormat.getTimeInstance(DateFormat.SHORT,
locale).format(date);
if (!model.isEmpty()) {
model.clear();
}
if (e.getID() == ActionEvent.ACTION_PERFORMED) {
model.addElement("Event Id: ACTION_PERFORMED");
}
model.addElement("Time: " + tm);
String source = e.getSource().getClass().getName();
model.addElement("Source: " + source);
int mod = e.getModifiers();
StringBuffer buffer = new StringBuffer("Modifiers: ");
if ((mod & ActionEvent.ALT_MASK) > 0) {
buffer.append("Alt ");
}
if ((mod & ActionEvent.SHIFT_MASK) > 0) {
buffer.append("Shift ");
}
if ((mod & ActionEvent.META_MASK) > 0) {
buffer.append("Meta ");
}
if ((mod & ActionEvent.CTRL_MASK) > 0) {
buffer.append("Ctrl ");
}
model.addElement(buffer);
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
EventObjectEx ex = new EventObjectEx();
ex.setVisible(true);
}
58
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
});
}
}
The
ClickAction
We get the time when the event occurred. The getWhen() method
returns time value in milliseconds. So we must format it
appropriately.
String source = e.getSource().getClass().getName();
model.addElement("Source: " + source);
Here we add the name of the source of the event to the list. In
our case the source is a JButton.
int mod = event.getModifiers();
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
if ((mod & ActionEvent.SHIFT_MASK) > 0)
buffer.append("Shift ");
Implementation
There are several ways, how we can implement event handling
in Java Swing toolkit.
Anonymous inner class
Inner class
Derived class
java.awt.Container;
java.awt.EventQueue;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
javax.swing.GroupLayout;
javax.swing.JButton;
javax.swing.JFrame;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
public AnonymousInnerClassEx() {
initUI();
}
private void initUI() {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
JButton closeButton = new JButton("Close");
closeButton.setBounds(40, 50, 80, 25);
closeButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
System.exit(0);
}
});
gl.setAutoCreateContainerGaps(true);
gl.setHorizontalGroup(gl.createSequentialGroup()
.addComponent(closeButton)
.addGap(220)
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addComponent(closeButton)
.addGap(180)
);
pack();
setTitle("Anonymous inner class");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
AnonymousInnerClassEx ex =
new AnonymousInnerClassEx();
ex.setVisible(true);
}
});
61
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
}
}
Inner class
Here
inner
we
implement
ActionListener class.
the
package com.zetcode;
import
import
import
import
import
import
import
java.awt.Container;
java.awt.EventQueue;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
javax.swing.GroupLayout;
javax.swing.JButton;
javax.swing.JFrame;
62
example
using
an
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
private void initUI() {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
JButton closeButton = new JButton("Close");
ButtonCloseListener listener = new ButtonCloseListener();
closeButton.addActionListener(listener);
gl.setAutoCreateContainerGaps(true);
gl.setHorizontalGroup(gl.createSequentialGroup()
.addComponent(closeButton)
.addGap(220)
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addComponent(closeButton)
.addGap(180)
);
pack();
setTitle("Inner class example");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private class ButtonCloseListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
InnerClassExample ex = new InnerClassExample();
ex.setVisible(true);
}
});
}
}
63
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
A derived
listener
class
implementing
the
java.awt.Container;
java.awt.EventQueue;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
javax.swing.GroupLayout;
javax.swing.JButton;
javax.swing.JFrame;
64
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
MyButton closeButton = new MyButton("Close");
gl.setAutoCreateContainerGaps(true);
gl.setHorizontalGroup(gl.createSequentialGroup()
.addComponent(closeButton)
.addGap(220)
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addComponent(closeButton)
.addGap(180)
);
pack();
setTitle("Derived class");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private class MyButton extends JButton
implements ActionListener {
public MyButton(String text) {
super.setText(text);
addActionListener(this);
}
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
DerivedClassExample ex = new DerivedClassExample();
ex.setVisible(true);
}
});
}
}
65
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
MyButton closeButton = new MyButton("Close");
Multiple sources
A listener can be plugged into several sources. This will be
explained in the next example.
package com.zetcode;
import
import
import
import
import
import
import
import
import
import
import
java.awt.BorderLayout;
java.awt.EventQueue;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
javax.swing.BorderFactory;
javax.swing.GroupLayout;
javax.swing.JButton;
javax.swing.JFrame;
static javax.swing.JFrame.EXIT_ON_CLOSE;
javax.swing.JLabel;
javax.swing.JPanel;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
}
private void initUI() {
JPanel panel = new JPanel();
GroupLayout gl = new GroupLayout(panel);
panel.setLayout(gl);
statusbar = new JLabel("ZetCode");
statusbar.setBorder(BorderFactory.createEtchedBorder());
ButtonListener butlist = new ButtonListener();
JButton closeButton = new JButton("Close");
closeButton.addActionListener(butlist);
JButton openButton = new JButton("Open");
openButton.addActionListener(butlist);
JButton findButton = new JButton("Find");
findButton.addActionListener(butlist);
JButton saveButton = new JButton("Save");
saveButton.addActionListener(butlist);
gl.setAutoCreateContainerGaps(true);
gl.setAutoCreateGaps(true);
gl.setHorizontalGroup(gl.createParallelGroup()
.addComponent(closeButton)
.addComponent(openButton)
.addComponent(findButton)
.addComponent(saveButton)
.addGap(250)
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addComponent(closeButton)
.addComponent(openButton)
.addComponent(findButton)
.addComponent(saveButton)
.addGap(20)
);
gl.linkSize(closeButton, openButton,
findButton, saveButton);
add(panel, BorderLayout.CENTER);
add(statusbar, BorderLayout.SOUTH);
pack();
67
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
setTitle("Multiple Sources");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private class ButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
JButton o = (JButton) e.getSource();
String label = o.getText();
statusbar.setText(" " + label + " button clicked");
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
MultipleSources ms = new MultipleSources();
ms.setVisible(true);
}
});
}
}
ButtonListener
object.
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
}
Multiple listeners
It is possible to register several listeners for one event.
package com.zetcode;
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
java.awt.BorderLayout;
java.awt.EventQueue;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
java.util.Calendar;
javax.swing.BorderFactory;
javax.swing.GroupLayout;
static javax.swing.GroupLayout.Alignment.CENTER;
static javax.swing.GroupLayout.DEFAULT_SIZE;
static javax.swing.GroupLayout.PREFERRED_SIZE;
javax.swing.JButton;
javax.swing.JFrame;
javax.swing.JLabel;
javax.swing.JPanel;
javax.swing.JSpinner;
javax.swing.SpinnerModel;
javax.swing.SpinnerNumberModel;
69
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
public MultipleListeners() {
initUI();
}
private void initUI() {
JPanel panel = new JPanel();
GroupLayout gl = new GroupLayout(panel);
panel.setLayout(gl);
add(panel, BorderLayout.CENTER);
statusbar = new JLabel("0");
statusbar.setBorder(BorderFactory.createEtchedBorder());
add(statusbar, BorderLayout.SOUTH);
JButton addButton = new JButton("+");
addButton.addActionListener(new ButtonListener1());
addButton.addActionListener(new ButtonListener2());
Calendar calendar = Calendar.getInstance();
int currentYear = calendar.get(Calendar.YEAR);
SpinnerModel yearModel = new SpinnerNumberModel(currentYear,
currentYear - 100,
currentYear + 100,
1);
spinner = new JSpinner(yearModel);
spinner.setEditor(new JSpinner.NumberEditor(spinner, "#"));
gl.setAutoCreateContainerGaps(true);
gl.setHorizontalGroup(gl.createSequentialGroup()
.addComponent(addButton)
.addGap(20)
.addComponent(spinner, DEFAULT_SIZE,
DEFAULT_SIZE, PREFERRED_SIZE)
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addGroup(gl.createParallelGroup(CENTER)
.addComponent(addButton)
.addComponent(spinner, DEFAULT_SIZE,
DEFAULT_SIZE, PREFERRED_SIZE))
);
pack();
setTitle("Multiple Listeners");
setSize(300, 200);
setLocationRelativeTo(null);
70
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private class ButtonListener1 implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
Integer val = (Integer) spinner.getValue();
spinner.setValue(++val);
}
}
private class ButtonListener2 implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
statusbar.setText(Integer.toString(++count));
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
MultipleListeners ml = new MultipleListeners();
ml.setVisible(true);
}
});
}
}
71
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
spinner = new JSpinner(yearModel);
Removing listeners
72
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
java.awt.Container;
java.awt.EventQueue;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
java.awt.event.ItemEvent;
java.awt.event.ItemListener;
javax.swing.GroupLayout;
javax.swing.JButton;
javax.swing.JCheckBox;
javax.swing.JFrame;
javax.swing.JLabel;
JLabel lbl;
JButton addButton;
JCheckBox activeBox;
ButtonListener buttonlistener;
int count = 0;
public RemoveListenerEx() {
initUI();
}
private void initUI() {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
addButton = new JButton("+");
buttonlistener = new ButtonListener();
activeBox = new JCheckBox("Active listener");
activeBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent event) {
if (activeBox.isSelected()) {
addButton.addActionListener(buttonlistener);
} else {
addButton.removeActionListener(buttonlistener);
}
73
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
}
});
lbl = new JLabel("0");
gl.setAutoCreateContainerGaps(true);
gl.setHorizontalGroup(gl.createSequentialGroup()
.addGroup(gl.createParallelGroup()
.addComponent(addButton)
.addComponent(lbl))
.addGap(30)
.addComponent(activeBox)
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addGroup(gl.createParallelGroup()
.addComponent(addButton)
.addComponent(activeBox))
.addGap(30)
.addComponent(lbl)
);
pack();
setTitle("Remove listener");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private class ButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
lbl.setText(Integer.toString(++count));
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
RemoveListenerEx ex = new RemoveListenerEx();
ex.setVisible(true);
}
});
}
}
74
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Moving a window
The following example will look for a position of a window on
the screen.
package com.zetcode;
import
import
import
import
import
import
import
import
java.awt.Container;
java.awt.EventQueue;
java.awt.Font;
java.awt.event.ComponentEvent;
java.awt.event.ComponentListener;
javax.swing.GroupLayout;
javax.swing.JFrame;
javax.swing.JLabel;
75
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
private JLabel labelx;
private JLabel labely;
public MovingWindowEx() {
initUI();
}
private void initUI() {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
addComponentListener(this);
labelx = new JLabel("x: ");
labelx.setFont(new Font("Serif", Font.BOLD, 14));
labelx.setBounds(20, 20, 60, 25);
labely = new JLabel("y: ");
labely.setFont(new Font("Serif", Font.BOLD, 14));
labely.setBounds(20, 45, 60, 25);
gl.setAutoCreateContainerGaps(true);
gl.setAutoCreateGaps(true);
gl.setHorizontalGroup(gl.createParallelGroup()
.addComponent(labelx)
.addComponent(labely)
.addGap(250)
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addComponent(labelx)
.addComponent(labely)
.addGap(130)
);
pack();
setTitle("Moving window");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
@Override
public void componentResized(ComponentEvent e) {
}
@Override
public void componentMoved(ComponentEvent e) {
76
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
int x = e.getComponent().getX();
int y = e.getComponent().getY();
labelx.setText("x: " + x);
labely.setText("y: " + y);
}
@Override
public void componentShown(ComponentEvent e) {
}
@Override
public void componentHidden(ComponentEvent e) {
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
MovingWindowEx ex = new MovingWindowEx();
ex.setVisible(true);
}
});
}
}
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
}
@Override
public void componentShown(ComponentEvent e) {
}
@Override
public void componentHidden(ComponentEvent e) {
}
Adapters
An adapter is a convenient class that provides empty
implementations all required methods. In the previous code
example, we had to implement all four methods of
a ComponentListener classeven if we did not use them. To avoid
unnecessary coding, we can use adapters. We then use
implement those methods that we actually need. There is no
adapter for a button click event because there we have only
one method to implementthe actionPerformed(). We can use
adapters in situations where we have more than one method to
implement.
78
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
java.awt.Container;
java.awt.EventQueue;
java.awt.Font;
java.awt.event.ComponentAdapter;
java.awt.event.ComponentEvent;
javax.swing.GroupLayout;
javax.swing.JFrame;
javax.swing.JLabel;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
pack();
setTitle("Adapter example");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private class MoveAdapter extends ComponentAdapter {
@Override
public void componentMoved(ComponentEvent e) {
int x = e.getComponent().getX();
int y = e.getComponent().getY();
labelx.setText("x: " + x);
labely.setText("y: " + y);
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
AdapterExample ex = new AdapterExample();
ex.setVisible(true);
}
});
}
}
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
}
}
Inside
the MoveAdapter inner
class,
we
define
the componentMoved() method. All the other methods are left
empty.
This part of the Java Swing tutorial was dedicated to Swing
events.
++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++
Lesson 5:
JLabel
is a simple component for displaying text, images or both.
It does not react to input events.
JLabel
package com.zetcode;
import
import
import
import
import
import
import
import
java.awt.Color;
java.awt.Container;
java.awt.EventQueue;
java.awt.Font;
javax.swing.GroupLayout;
javax.swing.JComponent;
javax.swing.JFrame;
javax.swing.JLabel;
81
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
public LabelEx() {
initUI();
}
private void initUI() {
String lyrics = "<html>It's way too late to think of<br>" +
"Someone I would call now<br>" +
"And neon signs got tired<br>" +
"Red eye flights help the stars out<br>" +
"I'm safe in a corner<br>" +
"Just hours before me<br>" +
"<br>" +
"I'm waking with the roaches<br>" +
"The world has surrendered<br>" +
"I'm dating ancient ghosts<br>" +
"The ones I made friends with<br>" +
"The comfort of fireflies<br>" +
"Long gone before daylight<br>" +
"<br>" +
"And if I had one wishful field tonight<br>" +
"I'd ask for the sun to never rise<br>" +
"If God leant his voice for me to speak<br>" +
"I'd say go to bed, world<br>" +
"<br>" +
"I've always been too late<br>" +
"To see what's before me<br>" +
"And I know nothing sweeter than<br>" +
"Champaign from last New Years<br>" +
"Sweet music in my ears<br>" +
"And a night full of no fears<br>" +
"<br>" +
"But if I had one wishful field tonight<br>" +
"I'd ask for the sun to never rise<br>" +
"If God passed a mic to me to speak<br>" +
"I'd say stay in bed, world<br>" +
"Sleep in peace</html>";
JLabel label = new JLabel(lyrics);
label.setFont(new Font("Serif", Font.PLAIN, 14));
label.setForeground(new Color(50, 50, 25));
createLayout(label);
setTitle("No Sleep");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private void createLayout(JComponent... arg) {
Container pane = getContentPane();
82
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
gl.setAutoCreateContainerGaps(true);
gl.setHorizontalGroup(gl.createSequentialGroup()
.addComponent(arg[0])
);
gl.setVerticalGroup(gl.createParallelGroup()
.addComponent(arg[0])
);
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
LabelEx ex = new LabelEx();
ex.setVisible(true);
}
});
}
}
83
so
that
the
label
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Figure: JLabel
JCheckBox
is a box with a label that has two states: on and off. If
the check box is selected, it is represented by a tick in a box. A
check box can be used to show or hide a splashscreen at
startup, toggle visibility of a toolbar etc.
JCheckBox
With JCheckBox it
is
possible
to
use
an ActionListener or
an ItemListener. Usually the latter option is used. ItemListener is the
interface for receiving item events. The class that is interested
in processing an item event, e.g. the observer, implements this
interface. The observer object is registered with a component
using the component's addItemListener() method. When an item
84
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
itemStateChanged()
package com.zetcode;
import
import
import
import
import
import
import
import
java.awt.Container;
java.awt.EventQueue;
java.awt.event.ItemEvent;
java.awt.event.ItemListener;
javax.swing.GroupLayout;
javax.swing.JCheckBox;
javax.swing.JComponent;
javax.swing.JFrame;
85
method
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
gl.setAutoCreateContainerGaps(true);
gl.setHorizontalGroup(gl.createParallelGroup()
.addComponent(arg[0])
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addComponent(arg[0])
);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
CheckBoxEx ex = new CheckBoxEx();
ex.setVisible(true);
}
});
}
}
cb.addItemListener(this);
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
if (sel==ItemEvent.SELECTED) {
setTitle("JCheckBox");
} else {
setTitle("");
}
}
Figure: JCheckBox
Note the blue rectangle around the text of the check box. It
indicates that this component has keyboard focus. It is possible
to select and deselect the check box with the Space key.
JSlider
is a component that lets the user graphically select a
value by sliding a knob within a bounded interval. Moving the
slider's
knob,
the stateChanged() method
of
the
slider's ChangeListeneris called. Our example will show a volume
control.
JSlider
package com.zetcode;
import java.awt.Container;
import java.awt.EventQueue;
import javax.swing.GroupLayout;
87
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
import
import
import
import
import
import
import
import
static javax.swing.GroupLayout.Alignment.CENTER;
javax.swing.ImageIcon;
javax.swing.JComponent;
javax.swing.JFrame;
javax.swing.JLabel;
javax.swing.JSlider;
javax.swing.event.ChangeEvent;
javax.swing.event.ChangeListener;
ImageIcon
ImageIcon
ImageIcon
ImageIcon
mute;
min;
med;
max;
public SliderEx() {
initUI();
}
private void initUI() {
loadImages();
slider = new JSlider(0, 150, 0);
slider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent event) {
int value = slider.getValue();
if (value == 0) {
lbl.setIcon(mute);
} else if (value > 0 && value <= 30) {
lbl.setIcon(min);
} else if (value > 30 && value < 80) {
lbl.setIcon(med);
} else {
lbl.setIcon(max);
}
}
});
lbl = new JLabel(mute, JLabel.CENTER);
createLayout(slider, lbl);
88
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
setTitle("JSlider");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
private void loadImages() {
mute = new ImageIcon("mute.png");
min = new ImageIcon("min.png");
med = new ImageIcon("med.png");
max = new ImageIcon("max.png");
}
private void createLayout(JComponent... arg) {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
gl.setAutoCreateContainerGaps(true);
gl.setAutoCreateGaps(true);
gl.setHorizontalGroup(gl.createSequentialGroup()
.addComponent(arg[0])
.addComponent(arg[1])
);
gl.setVerticalGroup(gl.createParallelGroup(CENTER)
.addComponent(arg[0])
.addComponent(arg[1])
);
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
SliderEx ex = new SliderEx();
ex.setVisible(true);
}
});
}
}
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
In the
loadImages()
slider.addChangeListener(new ChangeListener() {
...
});
Figure: JSlider
JComboBox
is a component that combines a button or editable
field and a drop-down list. The user can select a value from the
drop-down list, which appears at the user's request. If you make
the combo box editable, then the combo box includes an
editable field into which the user can type a value.
JComboBox
package com.zetcode;
import
import
import
import
java.awt.Container;
java.awt.EventQueue;
java.awt.event.ItemEvent;
java.awt.event.ItemListener;
import
import
import
import
import
import
javax.swing.GroupLayout;
static javax.swing.GroupLayout.Alignment.BASELINE;
javax.swing.JComboBox;
javax.swing.JComponent;
javax.swing.JFrame;
javax.swing.JLabel;
90
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
display.setText(e.getItem().toString());
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
ComboBoxEx ex = new ComboBoxEx();
ex.setVisible(true);
}
});
}
}
The
JComboBox
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
if (e.getStateChange() == ItemEvent.SELECTED) {
display.setText(e.getItem().toString());
}
}
Figure: JComboBox
JProgressBar
A progress bar is a component that is used when we process
lengthy tasks. It is animated so that the user knows that our
task is progressing. The JProgressBar component provides a
horizontal or a vertical progress bar. The initial and minimum
values are 0 and the maximum is 100.
package com.zetcode;
import
import
import
import
import
import
import
import
import
import
import
import
java.awt.Container;
java.awt.EventQueue;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
javax.swing.AbstractAction;
javax.swing.GroupLayout;
static javax.swing.GroupLayout.Alignment.CENTER;
javax.swing.JButton;
javax.swing.JComponent;
javax.swing.JFrame;
javax.swing.JProgressBar;
javax.swing.Timer;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
}
private void initUI() {
pbar = new JProgressBar();
pbar.setStringPainted(true);
sBtn = new JButton("Start");
sBtn.addActionListener(new ClickAction());
timer = new Timer(50, new UpdateBarListener());
createLayout(pbar, sBtn);
setTitle("JProgressBar");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
private void createLayout(JComponent... arg) {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
gl.setAutoCreateContainerGaps(true);
gl.setAutoCreateGaps(true);
gl.setHorizontalGroup(gl.createSequentialGroup()
.addComponent(arg[0])
.addComponent(arg[1])
);
gl.setVerticalGroup(gl.createParallelGroup(CENTER)
.addComponent(arg[0])
.addComponent(arg[1])
);
pack();
}
private class UpdateBarListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
int val = pbar.getValue();
if (val >= 100) {
timer.stop();
sBtn.setText("End");
return;
}
94
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
pbar.setValue(++val);
}
}
private class ClickAction extends AbstractAction {
@Override
public void actionPerformed(ActionEvent e) {
if (timer.isRunning()) {
timer.stop();
sBtn.setText("Start");
} else if (!"End".equals(sBtn.getText())) {
timer.start();
sBtn.setText("Stop");
}
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
ProgressBarEx ex = new ProgressBarEx();
ex.setVisible(true);
}
});
}
}
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
private class UpdateBarListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
int val = pbar.getValue();
if (val >= 100) {
timer.stop();
sBtn.setText("End");
return;
}
pbar.setValue(++val);
}
}
The button starts or stops the timer. The text of the button is
updated dynamically; it can have "Start", "Stop", or "End" string
values.
Figure: JProgressBar
JToggleButton
96
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
package com.zetcode;
import
import
import
import
import
import
import
import
import
import
import
import
import
import
java.awt.Color;
java.awt.Container;
java.awt.Dimension;
java.awt.EventQueue;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
javax.swing.GroupLayout;
static javax.swing.GroupLayout.Alignment.CENTER;
javax.swing.JComponent;
javax.swing.JFrame;
javax.swing.JPanel;
javax.swing.JToggleButton;
static javax.swing.LayoutStyle.ComponentPlacement.UNRELATED;
javax.swing.border.LineBorder;
JToggleButton redBtn;
JToggleButton greenBtn;
JToggleButton blueBtn;
JPanel display;
public ToggleButtonEx() {
initUI();
}
private void initUI() {
redBtn = new JToggleButton("red");
redBtn.addActionListener(this);
greenBtn = new JToggleButton("green");
greenBtn.addActionListener(this);
blueBtn = new JToggleButton("blue");
blueBtn.addActionListener(this);
display = new JPanel();
display.setPreferredSize(new Dimension(120, 120));
display.setBorder(LineBorder.createGrayLineBorder());
display.setBackground(Color.black);
createLayout(redBtn, greenBtn, blueBtn, display);
97
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
setTitle("JToggleButton");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private void createLayout(JComponent... arg) {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
gl.setAutoCreateContainerGaps(true);
gl.setAutoCreateGaps(true);
gl.setHorizontalGroup(gl.createSequentialGroup()
.addGroup(gl.createParallelGroup()
.addComponent(arg[0])
.addComponent(arg[1])
.addComponent(arg[2]))
.addPreferredGap(UNRELATED)
.addComponent(arg[3])
);
gl.setVerticalGroup(gl.createParallelGroup(CENTER)
.addGroup(gl.createSequentialGroup()
.addComponent(arg[0])
.addComponent(arg[1])
.addComponent(arg[2]))
.addComponent(arg[3])
);
gl.linkSize(redBtn, greenBtn, blueBtn);
pack();
}
@Override
public void actionPerformed(ActionEvent e) {
Color color = display.getBackground();
int red = color.getRed();
int green = color.getGreen();
int blue = color.getBlue();
if (e.getActionCommand().equals("red")) {
if (red == 0) {
red = 255;
} else {
red = 0;
}
}
98
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
if (e.getActionCommand().equals("green")) {
if (green == 0) {
green = 255;
} else {
green = 0;
}
}
if (e.getActionCommand().equals("blue")) {
if (blue == 0) {
blue = 255;
} else {
blue = 0;
}
}
Color setCol = new Color(red, green, blue);
display.setBackground(setCol);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
ToggleButtonEx ex = new ToggleButtonEx();
ex.setVisible(true);
}
});
}
}
The example has three toggle buttons and a panel. We set the
background colour of the display panel to black. The toggle
buttons will toggle the red, green, and blue parts of the colour
value. The background colour will depend on which toggle
buttons we have pressed.
redBtn = new JToggleButton("red");
redBtn.addActionListener(this);
This is the panel that shows the colour value mixed by toggle
buttons. We set its preferred size (the default is very small),
99
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Figure: JToggleButton
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
JList Component
is a component that displays a list of objects. It allows the
user to select one or more items.
JList
package com.zetcode;
import
import
import
import
java.awt.BorderLayout;
java.awt.Dimension;
java.awt.Font;
java.awt.GraphicsEnvironment;
import
import
import
import
import
import
import
import
import
javax.swing.BorderFactory;
javax.swing.JFrame;
javax.swing.JLabel;
javax.swing.JList;
javax.swing.JPanel;
javax.swing.JScrollPane;
javax.swing.SwingUtilities;
javax.swing.event.ListSelectionEvent;
javax.swing.event.ListSelectionListener;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
String[] fonts = ge.getAvailableFontFamilyNames();
We create a
JList
component.
We get the selected item and set a new font for the label.
JScrollPane pane = new JScrollPane();
pane.getViewport().add(list);
Figure: JList
JTextArea component
A JTextArea is a multiline text area that displays plain text. It is
lightweight component for working with text. The component
does
not
handle
scrolling.
For
this
task,
we
use JScrollPane component.
103
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
package com.zetcode;
import java.awt.BorderLayout;
import java.awt.Dimension;
import
import
import
import
import
import
javax.swing.BorderFactory;
javax.swing.JFrame;
javax.swing.JPanel;
javax.swing.JScrollPane;
javax.swing.JTextArea;
javax.swing.SwingUtilities;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
}
JTextArea
component.
JTextArea
component.
The setLineWrap() makes the lines wrapped if they are too long to
fit the text area's width.
area.setWrapStyleWord(true);
JTextArea
component into
Figure: JTextAra
JTextPane component
component is a more advanced component for working
with text. The component can do some complex formatting
operations over the text. It can display also HTML documents.
JTextPane
105
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
package com.zetcode;
import java.awt.BorderLayout;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import
import
import
import
import
import
javax.swing.BorderFactory;
javax.swing.JFrame;
javax.swing.JPanel;
javax.swing.JScrollPane;
javax.swing.JTextPane;
javax.swing.SwingUtilities;
106
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
try {
String cd = System.getProperty("user.dir") + "/";
textPane.setPage("File:///" + cd + "test.html");
} catch (IOException ex) {
Logger.getLogger(TextPaneExample.class.getName()).log(Level.SEVERE,
null, ex);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
TextPaneExample ex = new TextPaneExample();
ex.setVisible(true);
}
});
}
}
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
</body>
</html>
Figure: JTextPane
108
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Message dialogs
109
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
java.awt.Container;
java.awt.EventQueue;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
javax.swing.GroupLayout;
static javax.swing.GroupLayout.DEFAULT_SIZE;
javax.swing.JButton;
javax.swing.JComponent;
javax.swing.JFrame;
javax.swing.JOptionPane;
javax.swing.JPanel;
warBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
JOptionPane.showMessageDialog(pnl, "A deprecated call!",
"Warning", JOptionPane.WARNING_MESSAGE);
}
});
errBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
JOptionPane.showMessageDialog(pnl, "Could not open file!",
"Error", JOptionPane.ERROR_MESSAGE);
110
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
}
});
queBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
JOptionPane.showMessageDialog(pnl, "Are you sure to quit?",
"Question", JOptionPane.QUESTION_MESSAGE);
}
});
infBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
JOptionPane.showMessageDialog(pnl, "Download completed.",
"Information", JOptionPane.INFORMATION_MESSAGE);
}
});
createLayout(warBtn, errBtn , queBtn, infBtn);
setTitle("Message dialogs");
setSize(300, 200);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private void createLayout(JComponent... arg) {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
gl.setAutoCreateGaps(true);
gl.setHorizontalGroup(gl.createSequentialGroup()
.addContainerGap(DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(gl.createParallelGroup()
.addComponent(arg[0])
.addComponent(arg[2]))
.addGroup(gl.createParallelGroup()
.addComponent(arg[1])
.addComponent(arg[3]))
.addContainerGap(DEFAULT_SIZE, Short.MAX_VALUE)
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addContainerGap(DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(gl.createParallelGroup()
.addComponent(arg[0])
.addComponent(arg[1]))
111
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
.addGroup(gl.createParallelGroup()
.addComponent(arg[2])
.addComponent(arg[3]))
.addContainerGap(DEFAULT_SIZE, Short.MAX_VALUE)
);
gl.linkSize(arg[0], arg[1], arg[2], arg[3]);
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
MessageDialogsEx md = new MessageDialogsEx();
md.setVisible(true);
}
});
}
}
To
create
a
message
dialog,
we
call
the
static showMessageDialog() method of the JOptionPane class. We
provide the dialog's parent, message text, title and a message
type. The message type is one of the following constants:
ERROR_MESSAGE
WARNING_MESSAGE
QUESTION_MESSAGE
112
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
INFORMATION_MESSAGE
The displayed icon depends on this constant.
A custom dialog
In the following example we create a simple custom dialog. It is
a sample about dialog found in many GUI applications, usually
located in the Help menu.
package com.zetcode;
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
java.awt.Container;
java.awt.EventQueue;
java.awt.Font;
java.awt.Frame;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
java.awt.event.KeyEvent;
javax.swing.Box;
javax.swing.GroupLayout;
static javax.swing.GroupLayout.Alignment.CENTER;
javax.swing.ImageIcon;
javax.swing.JButton;
javax.swing.JComponent;
javax.swing.JDialog;
javax.swing.JFrame;
javax.swing.JLabel;
javax.swing.JMenu;
javax.swing.JMenuBar;
javax.swing.JMenuItem;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
114
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
pack();
}
}
public class JDialogEx extends JFrame
implements ActionListener {
public JDialogEx() {
initUI();
}
private void initUI() {
createMenuBar();
setTitle("Simple Dialog");
setSize(350, 250);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private void createMenuBar() {
JMenuBar menubar = new JMenuBar();
JMenu fileMenu = new JMenu("File");
fileMenu.setMnemonic(KeyEvent.VK_F);
JMenu helpMenu = new JMenu("Help");
helpMenu.setMnemonic(KeyEvent.VK_H);
JMenuItem aboutMi = new JMenuItem("About");
aboutMi.setMnemonic(KeyEvent.VK_A);
helpMenu.add(aboutMi);
aboutMi.addActionListener(this);
menubar.add(fileMenu);
menubar.add(Box.createGlue());
menubar.add(helpMenu);
setJMenuBar(menubar);
}
@Override
public void actionPerformed(ActionEvent e) {
showAboutDialog();
}
private void showAboutDialog() {
AboutDialog ad = new AboutDialog(this);
115
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
ad.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JDialogEx sd = new JDialogEx();
sd.setVisible(true);
}
});
}
}
From the Help menu, we can popup a small dialog box. The
dialog displays text, an icon, and a button.
class AboutDialog extends JDialog {
JDialog
class.
setModalityType(ModalityType.APPLICATION_MODAL);
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
is
shown
on
the
screen
with
JFileChooser
JFileChooser
system.
package com.zetcode;
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
java.awt.Container;
java.awt.EventQueue;
java.awt.event.ActionEvent;
java.io.File;
java.io.IOException;
java.nio.file.Files;
java.nio.file.Paths;
java.util.logging.Level;
java.util.logging.Logger;
javax.swing.AbstractAction;
javax.swing.GroupLayout;
static javax.swing.GroupLayout.DEFAULT_SIZE;
javax.swing.ImageIcon;
javax.swing.JButton;
javax.swing.JComponent;
javax.swing.JFileChooser;
javax.swing.JFrame;
javax.swing.JPanel;
javax.swing.JScrollPane;
javax.swing.JTextArea;
javax.swing.JToolBar;
javax.swing.filechooser.FileFilter;
javax.swing.filechooser.FileNameExtensionFilter;
117
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
.addGroup(gl.createSequentialGroup()
.addComponent(arg[1]))
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addComponent(arg[0])
.addGap(4)
.addComponent(arg[1])
);
pack();
}
public String readFile(File file) {
String content = "";
try {
content = new String(Files.readAllBytes(Paths.get(
file.getAbsolutePath())));
} catch (IOException ex) {
Logger.getLogger(FileChooserEx.class.getName()).log(
Level.SEVERE, null, ex);
}
return content;
}
private class OpenFileAction extends AbstractAction {
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser fdia = new JFileChooser();
FileFilter filter = new FileNameExtensionFilter("Java files",
"java");
fdia.addChoosableFileFilter(filter);
int ret = fdia.showDialog(panel, "Open file");
if (ret == JFileChooser.APPROVE_OPTION) {
File file = fdia.getSelectedFile();
String text = readFile(file);
area.setText(text);
}
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
119
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
public void run() {
FileChooserEx fcd = new FileChooserEx();
fcd.setVisible(true);
}
});
}
}
JFileChooser
to
Here we define the file filter. In our case, we will have Java files
with extension .java. We have also the default All files option.
int ret = fdia.showDialog(panel, "Open file");
Here we get the name of the selected file. We read the contents
of the file and set the text into the text area.
120
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Figure:
JFileChooser dialog
JColorChooser
JColorChooser
package com.zetcode;
import
import
import
import
import
import
java.awt.BorderLayout;
java.awt.Color;
java.awt.Container;
java.awt.EventQueue;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
import
import
import
import
import
import
import
import
import
import
javax.swing.BorderFactory;
javax.swing.GroupLayout;
static javax.swing.GroupLayout.DEFAULT_SIZE;
javax.swing.ImageIcon;
javax.swing.JButton;
javax.swing.JColorChooser;
javax.swing.JComponent;
javax.swing.JFrame;
javax.swing.JPanel;
javax.swing.JToolBar;
121
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
public ColorChooserEx() {
initUI();
}
private void initUI() {
colourPanel = new JPanel();
colourPanel.setBackground(Color.WHITE);
JToolBar toolbar = createToolBar();
createLayout(toolbar, colourPanel);
setTitle("JColorChooser");
setSize(400, 300);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private JToolBar createToolBar() {
ImageIcon open = new ImageIcon("colourdlg.png");
JToolBar toolbar = new JToolBar();
JButton openb = new JButton(open);
openb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Color color = JColorChooser.showDialog(colourPanel,
"Choose colour", Color.white);
colourPanel.setBackground(color);
}
});
toolbar.add(openb);
return toolbar;
}
private void createLayout(JComponent... arg) {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
gl.setHorizontalGroup(gl.createParallelGroup()
.addComponent(arg[0], DEFAULT_SIZE, DEFAULT_SIZE,
Short.MAX_VALUE)
.addGroup(gl.createSequentialGroup()
.addGap(30)
122
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
.addComponent(arg[1])
.addGap(30))
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addComponent(arg[0])
.addGap(30)
.addComponent(arg[1])
.addGap(30)
);
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
ColorChooserEx ccd = new ColorChooserEx();
ccd.setVisible(true);
}
});
}
}
This
code
shows
the
colour
chooser
dialog.
The showDialog() method returns the selected colour value. We
change the colourPanel's background to the newly selected colour.
In this part of the Java Swing tutorial, we have covered dialogs.
++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++
Lesson 8:
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
public int getValue() {
return getModel().getValue();
}
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
ButtonModel
The model is used for various kinds of buttons like push
buttons, check boxes, radio boxes and for menu items. The
following example illustrates the model for a JButton. We can
manage only the state of the button because no data can be
associated with a push button.
package com.zetcode;
import
import
import
import
import
import
import
import
import
import
import
import
java.awt.Container;
java.awt.EventQueue;
java.awt.event.ActionEvent;
javax.swing.AbstractAction;
javax.swing.DefaultButtonModel;
javax.swing.GroupLayout;
javax.swing.JButton;
javax.swing.JCheckBox;
javax.swing.JFrame;
javax.swing.JLabel;
javax.swing.event.ChangeEvent;
javax.swing.event.ChangeListener;
JButton okbtn;
JLabel enabledLbl;
JLabel pressedLbl;
JLabel armedLbl;
JCheckBox cb;
public ButtonModel() {
initUI();
}
private void initUI() {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
okbtn = new JButton("OK");
okbtn.addChangeListener(new DisabledChangeListener());
cb = new JCheckBox();
cb.setAction(new CheckBoxAction());
enabledLbl = new JLabel("Enabled: true");
pressedLbl = new JLabel("Pressed: false");
126
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
armedLbl = new JLabel("Armed: false");
gl.setAutoCreateContainerGaps(true);
gl.setAutoCreateGaps(true);
gl.setHorizontalGroup(gl.createParallelGroup()
.addGroup(gl.createSequentialGroup()
.addComponent(okbtn)
.addGap(80)
.addComponent(cb))
.addGroup(gl.createParallelGroup()
.addComponent(enabledLbl)
.addComponent(pressedLbl)
.addComponent(armedLbl))
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addGroup(gl.createParallelGroup()
.addComponent(okbtn)
.addComponent(cb))
.addGap(40)
.addGroup(gl.createSequentialGroup()
.addComponent(enabledLbl)
.addComponent(pressedLbl)
.addComponent(armedLbl))
);
pack();
setTitle("ButtonModel");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private class DisabledChangeListener implements ChangeListener {
@Override
public void stateChanged(ChangeEvent e) {
DefaultButtonModel model = (DefaultButtonModel) okbtn.getModel();
if (model.isEnabled()) {
enabledLbl.setText("Enabled: true");
} else {
enabledLbl.setText("Enabled: false");
}
if (model.isArmed()) {
armedLbl.setText("Armed: true");
} else {
armedLbl.setText("Armed: false");
}
127
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
if (model.isPressed()) {
pressedLbl.setText("Pressed: true");
} else {
pressedLbl.setText("Pressed: false");
}
}
}
private class CheckBoxAction extends AbstractAction {
public CheckBoxAction() {
super("Disabled");
}
@Override
public void actionPerformed(ActionEvent e) {
if (okbtn.isEnabled()) {
okbtn.setEnabled(false);
} else {
okbtn.setEnabled(true);
}
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
ButtonModel ex = new ButtonModel();
ex.setVisible(true);
}
});
}
}
We use a
ChangeListener
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
} else {
enabledLbl.setText("Enabled: false");
}
Figure: ButtonModel
Custom ButtonModel
In the previous example, we used a default button model. In
the following code example we will use our own button model.
129
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
package com.zetcode;
import
import
import
import
import
import
import
import
import
import
import
import
java.awt.Container;
java.awt.EventQueue;
java.awt.event.ActionEvent;
javax.swing.AbstractAction;
javax.swing.ButtonModel;
javax.swing.DefaultButtonModel;
javax.swing.GroupLayout;
javax.swing.JButton;
javax.swing.JCheckBox;
javax.swing.JFrame;
static javax.swing.JFrame.EXIT_ON_CLOSE;
javax.swing.JLabel;
JButton okbtn;
JLabel enabledLbl;
JLabel pressedLbl;
JLabel armedLbl;
JCheckBox cb;
public ButtonModel2() {
initUI();
}
private void initUI() {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
okbtn = new JButton("OK");
cb = new JCheckBox();
cb.setAction(new CheckBoxAction());
enabledLbl = new JLabel("Enabled: true");
pressedLbl = new JLabel("Pressed: false");
armedLbl = new JLabel("Armed: false");
ButtonModel model = new OkButtonModel();
okbtn.setModel(model);
gl.setAutoCreateContainerGaps(true);
gl.setAutoCreateGaps(true);
gl.setHorizontalGroup(gl.createParallelGroup()
.addGroup(gl.createSequentialGroup()
.addComponent(okbtn)
.addGap(80)
130
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
.addComponent(cb))
.addGroup(gl.createParallelGroup()
.addComponent(enabledLbl)
.addComponent(pressedLbl)
.addComponent(armedLbl))
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addGroup(gl.createParallelGroup()
.addComponent(okbtn)
.addComponent(cb))
.addGap(40)
.addGroup(gl.createSequentialGroup()
.addComponent(enabledLbl)
.addComponent(pressedLbl)
.addComponent(armedLbl))
);
pack();
setTitle("Custom button model");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private class OkButtonModel extends DefaultButtonModel {
@Override
public void setEnabled(boolean b) {
if (b) {
enabledLbl.setText("Enabled: true");
} else {
enabledLbl.setText("Enabled: false");
}
super.setEnabled(b);
}
@Override
public void setArmed(boolean b) {
if (b) {
armedLbl.setText("Armed: true");
} else {
armedLbl.setText("Armed: false");
}
super.setArmed(b);
}
@Override
public void setPressed(boolean b) {
if (b) {
pressedLbl.setText("Pressed: true");
131
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
} else {
pressedLbl.setText("Pressed: false");
}
super.setPressed(b);
}
}
private class CheckBoxAction extends AbstractAction {
public CheckBoxAction() {
super("Disabled");
}
@Override
public void actionPerformed(ActionEvent e) {
if (okbtn.isEnabled()) {
okbtn.setEnabled(false);
} else {
okbtn.setEnabled(true);
}
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
ButtonModel2 ex = new ButtonModel2();
ex.setVisible(true);
}
});
}
}
This example does the same thing as the previous one. The
difference is that we do not use a change listener and we use a
custom button model.
ButtonModel model = new OkButtonModel();
okbtn.setModel(model);
132
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
JList models
Several components have two models; JList is one of them. It
has the following models: theListModel and the ListSelectionModel.
The ListModel handles data and the ListSelectionModel works with the
selection state of the list. The following example uses both
models.
package com.zetcode;
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
java.awt.Container;
java.awt.EventQueue;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
java.awt.event.MouseAdapter;
java.awt.event.MouseEvent;
javax.swing.DefaultListModel;
javax.swing.GroupLayout;
static javax.swing.GroupLayout.Alignment.CENTER;
javax.swing.JButton;
javax.swing.JFrame;
javax.swing.JList;
javax.swing.JOptionPane;
javax.swing.JScrollPane;
javax.swing.ListSelectionModel;
133
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
private
private
private
private
private
private
DefaultListModel model;
JList list;
JButton remallbtn;
JButton addbtn;
JButton renbtn;
JButton delbtn;
public ListModels() {
initUI();
}
private void createList() {
model = new DefaultListModel();
model.addElement("Amelie");
model.addElement("Aguirre, der Zorn Gottes");
model.addElement("Fargo");
model.addElement("Exorcist");
model.addElement("Schindler's list");
list = new JList(model);
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
int index = list.locationToIndex(e.getPoint());
Object item = model.getElementAt(index);
String text = JOptionPane.showInputDialog("Rename item", item);
String newitem = null;
if (text != null) {
newitem = text.trim();
} else {
return;
}
if (!newitem.isEmpty()) {
model.remove(index);
model.add(index, newitem);
ListSelectionModel selmodel = list.getSelectionModel();
selmodel.setLeadSelectionIndex(index);
}
}
}
});
}
private void createButtons() {
134
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
remallbtn = new JButton("Remove All");
addbtn = new JButton("Add");
renbtn = new JButton("Rename");
delbtn = new JButton("Delete");
addbtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String text = JOptionPane.showInputDialog("Add a new item");
String item = null;
if (text != null) {
item = text.trim();
} else {
return;
}
if (!item.isEmpty()) {
model.addElement(item);
}
}
});
delbtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
ListSelectionModel selmodel = list.getSelectionModel();
int index = selmodel.getMinSelectionIndex();
if (index >= 0) {
model.remove(index);
}
}
});
renbtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ListSelectionModel selmodel = list.getSelectionModel();
int index = selmodel.getMinSelectionIndex();
if (index == -1) {
return;
}
Object item = model.getElementAt(index);
String text = JOptionPane.showInputDialog("Rename item", item);
String newitem = null;
135
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
if (text != null) {
newitem = text.trim();
} else {
return;
}
if (!newitem.isEmpty()) {
model.remove(index);
model.add(index, newitem);
}
}
});
remallbtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
model.clear();
}
});
}
private void initUI() {
createList();
createButtons();
JScrollPane scrollpane = new JScrollPane(list);
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
gl.setAutoCreateContainerGaps(true);
gl.setAutoCreateGaps(true);
gl.setHorizontalGroup(gl.createSequentialGroup()
.addComponent(scrollpane)
.addGroup(gl.createParallelGroup()
.addComponent(addbtn)
.addComponent(renbtn)
.addComponent(delbtn)
.addComponent(remallbtn))
);
gl.setVerticalGroup(gl.createParallelGroup(CENTER)
.addComponent(scrollpane)
.addGroup(gl.createSequentialGroup()
.addComponent(addbtn)
.addComponent(renbtn)
.addComponent(delbtn)
.addComponent(remallbtn))
);
136
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
if (!item.isEmpty()) {
model.addElement(item);
}
We add only items that are not equal to null and are not empty,
e.g. items that contain at least one character other than white
space. It makes no sense to add white spaces or null values
into the list.
ListSelectionModel selmodel = list.getSelectionModel();
int index = selmodel.getMinSelectionIndex();
if (index >= 0) {
model.remove(index);
}
This is the code that runs when we press the delete button. In
order to delete an item from the list, it must be selectedwe
must figure out the currently selected item. For this, we call
thegetSelectionModel() method. We get the selected index with
the getMinSelectionIndex() and
remove
the
item
with
the remove() method.
In this example we used both list models. We called the add(),
remove() and clear() methods of the list data model to work
with our data. And we used a list selection model in order to
find out the selected item.
A document model
138
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
java.awt.BorderLayout;
java.awt.EventQueue;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
javax.swing.BorderFactory;
javax.swing.ImageIcon;
javax.swing.JButton;
javax.swing.JFrame;
javax.swing.JPanel;
javax.swing.JScrollPane;
javax.swing.JTextPane;
javax.swing.JToolBar;
javax.swing.text.Style;
javax.swing.text.StyleConstants;
javax.swing.text.StyledDocument;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
toolbar.add(boldb);
toolbar.add(italb);
toolbar.add(strib);
toolbar.add(undeb);
add(toolbar, BorderLayout.NORTH);
boldb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
sdoc.setCharacterAttributes(textpane.getSelectionStart(),
textpane.getSelectionEnd() - textpane.getSelectionStart(),
textpane.getStyle("Bold"), false);
}
});
italb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
sdoc.setCharacterAttributes(textpane.getSelectionStart(),
textpane.getSelectionEnd() - textpane.getSelectionStart(),
textpane.getStyle("Italic"), false);
}
});
strib.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
sdoc.setCharacterAttributes(textpane.getSelectionStart(),
textpane.getSelectionEnd() - textpane.getSelectionStart(),
textpane.getStyle("Strike"), false);
}
});
140
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
undeb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
sdoc.setCharacterAttributes(textpane.getSelectionStart(),
textpane.getSelectionEnd() - textpane.getSelectionStart(),
textpane.getStyle("Underline"), false);
}
});
}
private void initStyles(JTextPane textpane) {
Style style = textpane.addStyle("Bold", null);
StyleConstants.setBold(style, true);
style = textpane.addStyle("Italic", null);
StyleConstants.setItalic(style, true);
style = textpane.addStyle("Underline", null);
StyleConstants.setUnderline(style, true);
style = textpane.addStyle("Strike", null);
StyleConstants.setStrikeThrough(style, true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
DocumentModel ex = new DocumentModel();
ex.setVisible(true);
}
});
}
}
Here we get the styled document which is a model for the text
pane component.
Style style = textpane.addStyle("Bold", null);
StyleConstants.setBold(style, true);
141
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Figure:
Document
model
In this chapter we have mentioned Swing models.
++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++
Lesson 9:
142
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
are some methods that return data without the need for a
programmer to access the model.
public int getValue() {
return getModel().getValue();
}
144
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
ButtonModel
The model is used for various kinds of buttons like push
buttons, check boxes, radio boxes and for menu items. The
following example illustrates the model for a JButton. We can
manage only the state of the button because no data can be
associated with a push button.
package com.zetcode;
import
import
import
import
import
import
import
import
import
import
import
import
java.awt.Container;
java.awt.EventQueue;
java.awt.event.ActionEvent;
javax.swing.AbstractAction;
javax.swing.DefaultButtonModel;
javax.swing.GroupLayout;
javax.swing.JButton;
javax.swing.JCheckBox;
javax.swing.JFrame;
javax.swing.JLabel;
javax.swing.event.ChangeEvent;
javax.swing.event.ChangeListener;
JButton okbtn;
JLabel enabledLbl;
JLabel pressedLbl;
JLabel armedLbl;
JCheckBox cb;
public ButtonModel() {
initUI();
}
private void initUI() {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
okbtn = new JButton("OK");
okbtn.addChangeListener(new DisabledChangeListener());
145
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
cb = new JCheckBox();
cb.setAction(new CheckBoxAction());
enabledLbl = new JLabel("Enabled: true");
pressedLbl = new JLabel("Pressed: false");
armedLbl = new JLabel("Armed: false");
gl.setAutoCreateContainerGaps(true);
gl.setAutoCreateGaps(true);
gl.setHorizontalGroup(gl.createParallelGroup()
.addGroup(gl.createSequentialGroup()
.addComponent(okbtn)
.addGap(80)
.addComponent(cb))
.addGroup(gl.createParallelGroup()
.addComponent(enabledLbl)
.addComponent(pressedLbl)
.addComponent(armedLbl))
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addGroup(gl.createParallelGroup()
.addComponent(okbtn)
.addComponent(cb))
.addGap(40)
.addGroup(gl.createSequentialGroup()
.addComponent(enabledLbl)
.addComponent(pressedLbl)
.addComponent(armedLbl))
);
pack();
setTitle("ButtonModel");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private class DisabledChangeListener implements ChangeListener {
@Override
public void stateChanged(ChangeEvent e) {
DefaultButtonModel model = (DefaultButtonModel) okbtn.getModel();
if (model.isEnabled()) {
enabledLbl.setText("Enabled: true");
} else {
enabledLbl.setText("Enabled: false");
}
if (model.isArmed()) {
146
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
armedLbl.setText("Armed: true");
} else {
armedLbl.setText("Armed: false");
}
if (model.isPressed()) {
pressedLbl.setText("Pressed: true");
} else {
pressedLbl.setText("Pressed: false");
}
}
}
private class CheckBoxAction extends AbstractAction {
public CheckBoxAction() {
super("Disabled");
}
@Override
public void actionPerformed(ActionEvent e) {
if (okbtn.isEnabled()) {
okbtn.setEnabled(false);
} else {
okbtn.setEnabled(true);
}
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
ButtonModel ex = new ButtonModel();
ex.setVisible(true);
}
});
}
}
We use a
ChangeListener
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Figure: ButtonModel
Custom ButtonModel
148
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
java.awt.Container;
java.awt.EventQueue;
java.awt.event.ActionEvent;
javax.swing.AbstractAction;
javax.swing.ButtonModel;
javax.swing.DefaultButtonModel;
javax.swing.GroupLayout;
javax.swing.JButton;
javax.swing.JCheckBox;
javax.swing.JFrame;
static javax.swing.JFrame.EXIT_ON_CLOSE;
javax.swing.JLabel;
JButton okbtn;
JLabel enabledLbl;
JLabel pressedLbl;
JLabel armedLbl;
JCheckBox cb;
public ButtonModel2() {
initUI();
}
private void initUI() {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
okbtn = new JButton("OK");
cb = new JCheckBox();
cb.setAction(new CheckBoxAction());
enabledLbl = new JLabel("Enabled: true");
pressedLbl = new JLabel("Pressed: false");
armedLbl = new JLabel("Armed: false");
ButtonModel model = new OkButtonModel();
okbtn.setModel(model);
gl.setAutoCreateContainerGaps(true);
gl.setAutoCreateGaps(true);
149
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
gl.setHorizontalGroup(gl.createParallelGroup()
.addGroup(gl.createSequentialGroup()
.addComponent(okbtn)
.addGap(80)
.addComponent(cb))
.addGroup(gl.createParallelGroup()
.addComponent(enabledLbl)
.addComponent(pressedLbl)
.addComponent(armedLbl))
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addGroup(gl.createParallelGroup()
.addComponent(okbtn)
.addComponent(cb))
.addGap(40)
.addGroup(gl.createSequentialGroup()
.addComponent(enabledLbl)
.addComponent(pressedLbl)
.addComponent(armedLbl))
);
pack();
setTitle("Custom button model");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private class OkButtonModel extends DefaultButtonModel {
@Override
public void setEnabled(boolean b) {
if (b) {
enabledLbl.setText("Enabled: true");
} else {
enabledLbl.setText("Enabled: false");
}
super.setEnabled(b);
}
@Override
public void setArmed(boolean b) {
if (b) {
armedLbl.setText("Armed: true");
} else {
armedLbl.setText("Armed: false");
}
super.setArmed(b);
}
150
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
@Override
public void setPressed(boolean b) {
if (b) {
pressedLbl.setText("Pressed: true");
} else {
pressedLbl.setText("Pressed: false");
}
super.setPressed(b);
}
}
private class CheckBoxAction extends AbstractAction {
public CheckBoxAction() {
super("Disabled");
}
@Override
public void actionPerformed(ActionEvent e) {
if (okbtn.isEnabled()) {
okbtn.setEnabled(false);
} else {
okbtn.setEnabled(true);
}
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
ButtonModel2 ex = new ButtonModel2();
ex.setVisible(true);
}
});
}
}
This example does the same thing as the previous one. The
difference is that we do not use a change listener and we use a
custom button model.
ButtonModel model = new OkButtonModel();
okbtn.setModel(model);
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
...
}
JList models
Several components have two models; JList is one of them. It
has the following models: theListModel and the ListSelectionModel.
The ListModel handles data and the ListSelectionModel works with the
selection state of the list. The following example uses both
models.
package com.zetcode;
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
java.awt.Container;
java.awt.EventQueue;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
java.awt.event.MouseAdapter;
java.awt.event.MouseEvent;
javax.swing.DefaultListModel;
javax.swing.GroupLayout;
static javax.swing.GroupLayout.Alignment.CENTER;
javax.swing.JButton;
javax.swing.JFrame;
javax.swing.JList;
javax.swing.JOptionPane;
javax.swing.JScrollPane;
javax.swing.ListSelectionModel;
152
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
DefaultListModel model;
JList list;
JButton remallbtn;
JButton addbtn;
JButton renbtn;
JButton delbtn;
public ListModels() {
initUI();
}
private void createList() {
model = new DefaultListModel();
model.addElement("Amelie");
model.addElement("Aguirre, der Zorn Gottes");
model.addElement("Fargo");
model.addElement("Exorcist");
model.addElement("Schindler's list");
list = new JList(model);
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
int index = list.locationToIndex(e.getPoint());
Object item = model.getElementAt(index);
String text = JOptionPane.showInputDialog("Rename item", item);
String newitem = null;
if (text != null) {
newitem = text.trim();
} else {
return;
}
if (!newitem.isEmpty()) {
model.remove(index);
model.add(index, newitem);
ListSelectionModel selmodel = list.getSelectionModel();
selmodel.setLeadSelectionIndex(index);
}
}
}
});
}
153
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
154
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Object item = model.getElementAt(index);
String text = JOptionPane.showInputDialog("Rename item", item);
String newitem = null;
if (text != null) {
newitem = text.trim();
} else {
return;
}
if (!newitem.isEmpty()) {
model.remove(index);
model.add(index, newitem);
}
}
});
remallbtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
model.clear();
}
});
}
private void initUI() {
createList();
createButtons();
JScrollPane scrollpane = new JScrollPane(list);
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
gl.setAutoCreateContainerGaps(true);
gl.setAutoCreateGaps(true);
gl.setHorizontalGroup(gl.createSequentialGroup()
.addComponent(scrollpane)
.addGroup(gl.createParallelGroup()
.addComponent(addbtn)
.addComponent(renbtn)
.addComponent(delbtn)
.addComponent(remallbtn))
);
gl.setVerticalGroup(gl.createParallelGroup(CENTER)
.addComponent(scrollpane)
.addGroup(gl.createSequentialGroup()
.addComponent(addbtn)
.addComponent(renbtn)
155
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
.addComponent(delbtn)
.addComponent(remallbtn))
);
gl.linkSize(addbtn, renbtn, delbtn, remallbtn);
pack();
setTitle("JList models");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
ListModels ex = new ListModels();
ex.setVisible(true);
}
});
}
}
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
return;
}
if (!item.isEmpty()) {
model.addElement(item);
}
We add only items that are not equal to null and are not empty,
e.g. items that contain at least one character other than white
space. It makes no sense to add white spaces or null values
into the list.
ListSelectionModel selmodel = list.getSelectionModel();
int index = selmodel.getMinSelectionIndex();
if (index >= 0) {
model.remove(index);
}
This is the code that runs when we press the delete button. In
order to delete an item from the list, it must be selectedwe
must figure out the currently selected item. For this, we call
thegetSelectionModel() method. We get the selected index with
the getMinSelectionIndex() and
remove
the
item
with
the remove() method.
In this example we used both list models. We called the add(),
remove() and clear() methods of the list data model to work
with our data. And we used a list selection model in order to
find out the selected item.
A document model
157
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
java.awt.BorderLayout;
java.awt.EventQueue;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
javax.swing.BorderFactory;
javax.swing.ImageIcon;
javax.swing.JButton;
javax.swing.JFrame;
javax.swing.JPanel;
javax.swing.JScrollPane;
javax.swing.JTextPane;
javax.swing.JToolBar;
javax.swing.text.Style;
javax.swing.text.StyleConstants;
javax.swing.text.StyledDocument;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
toolbar.add(boldb);
toolbar.add(italb);
toolbar.add(strib);
toolbar.add(undeb);
add(toolbar, BorderLayout.NORTH);
boldb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
sdoc.setCharacterAttributes(textpane.getSelectionStart(),
textpane.getSelectionEnd() - textpane.getSelectionStart(),
textpane.getStyle("Bold"), false);
}
});
italb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
sdoc.setCharacterAttributes(textpane.getSelectionStart(),
textpane.getSelectionEnd() - textpane.getSelectionStart(),
textpane.getStyle("Italic"), false);
}
});
strib.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
sdoc.setCharacterAttributes(textpane.getSelectionStart(),
textpane.getSelectionEnd() - textpane.getSelectionStart(),
textpane.getStyle("Strike"), false);
}
});
159
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
undeb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
sdoc.setCharacterAttributes(textpane.getSelectionStart(),
textpane.getSelectionEnd() - textpane.getSelectionStart(),
textpane.getStyle("Underline"), false);
}
});
}
private void initStyles(JTextPane textpane) {
Style style = textpane.addStyle("Bold", null);
StyleConstants.setBold(style, true);
style = textpane.addStyle("Italic", null);
StyleConstants.setItalic(style, true);
style = textpane.addStyle("Underline", null);
StyleConstants.setUnderline(style, true);
style = textpane.addStyle("Strike", null);
StyleConstants.setStrikeThrough(style, true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
DocumentModel ex = new DocumentModel();
ex.setVisible(true);
}
});
}
}
Here we get the styled document which is a model for the text
pane component.
Style style = textpane.addStyle("Bold", null);
StyleConstants.setBold(style, true);
160
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Figure:
Document
model
In this chapter we have mentioned Swing models.
++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++
Lesson 10:
161
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
javax.swing.JButton;
javax.swing.JFrame;
javax.swing.JTextField;
javax.swing.TransferHandler;
163
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
field.setDragEnabled(true);
button.setTransferHandler(new TransferHandler("text"));
setSize(330, 150);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
new SimpleDnD();
}
}
Figure:
Simple
drag
&
drop
example
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
import
import
import
import
java.awt.FlowLayout;
java.awt.event.MouseAdapter;
java.awt.event.MouseEvent;
java.awt.event.MouseListener;
import
import
import
import
import
import
import
javax.swing.ImageIcon;
javax.swing.JButton;
javax.swing.JComponent;
javax.swing.JFrame;
javax.swing.JLabel;
javax.swing.JPanel;
javax.swing.TransferHandler;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
public void mousePressed(MouseEvent e) {
JComponent c = (JComponent) e.getSource();
TransferHandler handler = c.getTransferHandler();
handler.exportAsDrag(c, e, TransferHandler.COPY);
}
}
public static void main(String[] args) {
new IconDnD();
}
}
These code lines initiate the drag support. We get the drag
source. In our case it is a label instance. We get its transfer
handler object and finally initiate the drag support with
the exportAsDrag()method call.
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
java.awt.Dimension;
java.awt.FlowLayout;
java.awt.datatransfer.DataFlavor;
java.awt.datatransfer.Transferable;
import
import
import
import
import
import
import
import
import
javax.swing.DefaultListModel;
javax.swing.DropMode;
javax.swing.JFrame;
javax.swing.JList;
javax.swing.JPanel;
javax.swing.JScrollPane;
javax.swing.JTextField;
javax.swing.ListSelectionModel;
javax.swing.TransferHandler;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
panel.add(field);
pane.getViewport().add(list);
panel.add(pane);
add(panel);
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}
private class ListHandler extends TransferHandler {
public boolean canImport(TransferSupport support) {
if (!support.isDrop()) {
return false;
}
return support.isDataFlavorSupported(DataFlavor.stringFlavor);
}
public boolean importData(TransferSupport support) {
if (!canImport(support)) {
return false;
}
Transferable transferable = support.getTransferable();
String line;
try {
line = (String) transferable.getTransferData(DataFlavor.stringFlavor);
} catch (Exception e) {
return false;
}
JList.DropLocation dl = (JList.DropLocation) support.getDropLocation();
int index = dl.getIndex();
String[] data = line.split(",");
for (String item: data) {
if (!item.isEmpty())
model.add(index++, item.trim());
}
return true;
}
}
public static void main(String[] args) {
new ListDrop();
}
}
168
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
The
Transferable
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
We get a drop location for the list. We retrieve the index, where
the data will be inserted.
String[] data = line.split(",");
for (String item: data) {
if (!item.isEmpty())
model.add(index++, item.trim());
}
Here we split the text into parts and insert it into one or more
rows.
Drag Gesture
In the following example we will inspect a simple drag gesture.
We will work with several classes needed to create a drag
gesture.
A DragSource, DragGestureEvent, DragGestureListener, Transferable.
import
import
import
import
import
import
import
import
import
import
java.awt.Color;
java.awt.Cursor;
java.awt.Dimension;
java.awt.FlowLayout;
java.awt.datatransfer.DataFlavor;
java.awt.datatransfer.Transferable;
java.awt.dnd.DnDConstants;
java.awt.dnd.DragGestureEvent;
java.awt.dnd.DragGestureListener;
java.awt.dnd.DragSource;
170
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
import javax.swing.JFrame;
import javax.swing.JPanel;
public class DragGesture extends JFrame implements
DragGestureListener, Transferable {
public DragGesture() {
setTitle("Drag Gesture");
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 50, 15));
JPanel left = new JPanel();
left.setBackground(Color.red);
left.setPreferredSize(new Dimension(120, 120));
DragSource ds = new DragSource();
ds.createDefaultDragGestureRecognizer(left,
DnDConstants.ACTION_COPY, this);
panel.add(left);
add(panel);
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}
public void dragGestureRecognized(DragGestureEvent event) {
System.out.println("grag gesture");
Cursor cursor = null;
if (event.getDragAction() == DnDConstants.ACTION_COPY) {
cursor = DragSource.DefaultCopyDrop;
}
event.startDrag(cursor, this);
}
public static void main(String[] args) {
new DragGesture();
}
public Object getTransferData(DataFlavor flavor) {
return null;
}
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[0];
}
public boolean isDataFlavorSupported(DataFlavor flavor) {
return false;
171
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
}
}
The
DragGesture
implements
two
interfaces.
The DragGestureListener will
listen
for
drag
gestures.
The Transferable handles data for a transfer operation. In the
example, we will not transfer any data. We will only
demonstrate a drag gesture. So the three necessary methods
of the Transferableinterface are left unimplemented.
DragSource ds = new DragSource();
ds.createDefaultDragGestureRecognizer(left,
DnDConstants.ACTION_COPY, this);
The
dragGestureRecognized()
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[0];
}
public boolean isDataFlavorSupported(DataFlavor flavor) {
return false;
}
java.awt.Color;
java.awt.Cursor;
java.awt.Dimension;
java.awt.FlowLayout;
java.awt.datatransfer.DataFlavor;
java.awt.datatransfer.Transferable;
java.awt.datatransfer.UnsupportedFlavorException;
java.awt.dnd.DnDConstants;
java.awt.dnd.DragGestureEvent;
java.awt.dnd.DragGestureListener;
java.awt.dnd.DragSource;
java.awt.dnd.DropTarget;
java.awt.dnd.DropTargetAdapter;
java.awt.dnd.DropTargetDropEvent;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
import
import
import
import
javax.swing.JButton;
javax.swing.JColorChooser;
javax.swing.JFrame;
javax.swing.JPanel;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
175
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
public DataFlavor[] getTransferDataFlavors() { return supportedFlavors; }
public boolean isDataFlavorSupported(DataFlavor flavor) {
if (flavor.equals(colorFlavor) ||
flavor.equals(DataFlavor.stringFlavor)) return true;
return false;
}
public Object getTransferData(DataFlavor flavor)
throws UnsupportedFlavorException
{
if (flavor.equals(colorFlavor))
return color;
else if (flavor.equals(DataFlavor.stringFlavor))
return color.toString();
else
throw new UnsupportedFlavorException(flavor);
}
}
The code example shows a button and two panels. The button
displays a colour chooser dialog and sets a colour for the first
panel. The colour can be dragged into the second panel.
This example will enhance the previous one. We will add a drop
target and a custom transferable object.
new MyDropTargetListener(right);
has
two
parameters.
cursor
and
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
this.panel.setBackground(color);
event.dropComplete(true);
return;
}
If the conditions for a drag and drop operation are not fulfilled,
we reject it.
protected static DataFlavor colorFlavor =
new DataFlavor(Color.class, "A Color Object");
In the
TransferableColor,
we create a new
DataFlavor
object.
Figure: A
complex example
This part of the Java Swing tutorial was dedicated to Swing drap
and drop operations.
177
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++
Lesson 11:
Painting in Swing
Swing's painting system is able to render vector graphics,
images, and outline font-based text. Painting is needed in
applications when we want to change or enhance an existing
widget, or if we are creating a custom widget from scratch To
do the painting, we use the painting API provided by the Swing
toolkit.
The painting is done within the paintComponent() method. In the
painting process, we use theGraphics2D object.
2D Vector Graphics
There are two different computer graphics. Vector and raster
graphics. Raster graphics represents images as a collection of
pixels. Vector graphics is the use of geometrical primitives such
as points, lines, curves or polygons to represent images. These
primitives are created using mathematical equations.
Both types of computer graphics have advantages and
disadvantages. The advantages of vector graphics over raster
are:
smaller size
Types of primitives
points
178
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
lines
polylines
polygons
circles
ellipses
Splines
Points
The most simple graphics primitive is point. It is a single dot on
the window. There is no method to draw a point in Swing. To
draw a point, we use the drawLine() method. We use one point
twice.
package com.zetcode;
import
import
import
import
import
import
import
import
import
java.awt.Color;
java.awt.Dimension;
java.awt.Graphics;
java.awt.Graphics2D;
java.awt.Insets;
java.util.Random;
javax.swing.JFrame;
javax.swing.JPanel;
javax.swing.SwingUtilities;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
180
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Graphics2D
object.
g2d.setColor(Color.blue);
181
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Figure: Points
Lines
A line is a simple graphics primitive. It is drawn using two
points.
package com.zetcode;
import
import
import
import
import
import
java.awt.BasicStroke;
java.awt.Graphics;
java.awt.Graphics2D;
javax.swing.JFrame;
javax.swing.JPanel;
javax.swing.SwingUtilities;
dash1
dash2
dash3
dash4
=
=
=
=
{2f,
{1f,
{4f,
{4f,
0f,
1f,
0f,
4f,
2f};
1f};
2f};
1f};
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
g2d.setStroke(bs1);
g2d.drawLine(20, 80, 250, 80);
g2d.setStroke(bs2);
g2d.drawLine(20, 120, 250, 120);
g2d.setStroke(bs3);
g2d.drawLine(20, 160, 250, 160);
g2d.setStroke(bs4);
g2d.drawLine(20, 200, 250, 200);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
doDrawing(g);
}
}
public class LinesExample extends JFrame {
public LinesExample() {
initUI();
}
public final void initUI() {
DrawPanel dpnl = new DrawPanel();
add(dpnl);
setSize(280, 270);
setTitle("Lines");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
LinesExample ex = new LinesExample();
ex.setVisible(true);
}
});
}
}
In the example, we draw five lines. The first line is drawn using
the default values. Other will have a different stroke. The stroke
183
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
This code creates a stroke. The stroke defines the line width,
end caps, line joins, miter limit, dash and the dash phase.
Figure: Lines
Rectangles
To draw rectangles, we use the drawRect() method. To fill
rectangles with the current color, we use the fillRect() method.
package com.zetcode;
import
import
import
import
import
import
java.awt.Color;
java.awt.Graphics;
java.awt.Graphics2D;
javax.swing.JFrame;
javax.swing.JPanel;
javax.swing.SwingUtilities;
184
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
g2d.setColor(new Color(212, 212, 212));
g2d.drawRect(10, 15, 90, 60);
g2d.drawRect(130, 15, 90, 60);
g2d.drawRect(250, 15, 90, 60);
g2d.drawRect(10, 105, 90, 60);
g2d.drawRect(130, 105, 90, 60);
g2d.drawRect(250, 105, 90, 60);
g2d.drawRect(10, 195, 90, 60);
g2d.drawRect(130, 195, 90, 60);
g2d.drawRect(250, 195, 90, 60);
g2d.setColor(new Color(125, 167, 116));
g2d.fillRect(10, 15, 90, 60);
g2d.setColor(new Color(42, 179, 231));
g2d.fillRect(130, 15, 90, 60);
g2d.setColor(new Color(70, 67, 123));
g2d.fillRect(250, 15, 90, 60);
g2d.setColor(new Color(130, 100, 84));
g2d.fillRect(10, 105, 90, 60);
g2d.setColor(new Color(252, 211, 61));
g2d.fillRect(130, 105, 90, 60);
g2d.setColor(new Color(241, 98, 69));
g2d.fillRect(250, 105, 90, 60);
g2d.setColor(new Color(217, 146, 54));
g2d.fillRect(10, 195, 90, 60);
g2d.setColor(new Color(63, 121, 186));
g2d.fillRect(130, 195, 90, 60);
g2d.setColor(new Color(31, 21, 1));
g2d.fillRect(250, 195, 90, 60);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
doDrawing(g);
}
}
public class RectanglesExample extends JFrame {
public RectanglesExample() {
initUI();
}
185
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
public final void initUI() {
DrawPanel dpnl = new DrawPanel();
add(dpnl);
setSize(360, 300);
setTitle("Rectangles");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
RectanglesExample ex = new RectanglesExample();
ex.setVisible(true);
}
});
}
}
186
fillRect()
method.
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Figure: Rectangles
Textures
A texture is a bitmap image applied to a shape. To work with
textures in Java 2D, we use theTexturePaint class.
package com.zetcode;
import
import
import
import
import
java.awt.Graphics;
java.awt.Graphics2D;
java.awt.Rectangle;
java.awt.TexturePaint;
java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
import
import
import
import
import
java.io.IOException;
java.util.logging.Logger;
java.util.logging.Level;
javax.imageio.ImageIO;
javax.swing.SwingUtilities;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
loadImages();
}
private void loadImages() {
try {
slate = ImageIO.read(this.getClass().getResource("slate.png"));
java = ImageIO.read(this.getClass().getResource("java.png"));
pane = ImageIO.read(this.getClass().getResource("pane.png"));
} catch (IOException ex) {
Logger.getLogger(Textures.class.getName()).log(Level.SEVERE,
null, ex);
}
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
doDrawing(g);
}
private void doDrawing(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
slatetp = new TexturePaint(slate, new Rectangle(0, 0, 90, 60));
javatp = new TexturePaint(java, new Rectangle(0, 0, 90, 60));
panetp = new TexturePaint(pane, new Rectangle(0, 0, 90, 60));
g2d.setPaint(slatetp);
g2d.fillRect(10, 15, 90, 60);
g2d.setPaint(javatp);
g2d.fillRect(130, 15, 90, 60);
g2d.setPaint(panetp);
g2d.fillRect(250, 15, 90, 60);
}
}
public class Textures extends JFrame {
public Textures() {
initUI();
}
public final void initUI() {
DrawPanel dpnl = new DrawPanel();
add(dpnl);
188
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
setSize(360, 120);
setTitle("Textures");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Textures ex = new Textures();
ex.setVisible(true);
}
});
}
}
We create a
TexturePaint
g2d.setPaint(slatetp);
g2d.fillRect(10, 15, 90, 60);
Figure: Textures
Gradients
In computer graphics, gradient is a smooth blending of shades
from light to dark or from one colour to another. In 2D drawing
programs and paint programs, gradients are used to create
colourful backgrounds and special effects as well as to simulate
lights and shadows. (answers.com)
189
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
package com.zetcode;
import
import
import
import
import
import
import
java.awt.Color;
java.awt.GradientPaint;
java.awt.Graphics;
java.awt.Graphics2D;
javax.swing.JFrame;
javax.swing.JPanel;
javax.swing.SwingUtilities;
190
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
}
public class GradientsExample extends JFrame {
public GradientsExample() {
initUI();
}
public final void initUI() {
DrawPanel dpnl = new DrawPanel();
add(dpnl);
setSize(350, 350);
setTitle("Gradients");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
GradientsExample ex = new GradientsExample();
ex.setVisible(true);
}
});
}
}
191
setPaint()
method.
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Figure: Gradients
Drawing text
Drawing is done with the drawString() method. We specify the
string we want to draw and the position of the text on the
window area.
package com.zetcode;
import
import
import
import
import
import
import
java.awt.Font;
java.awt.Graphics;
java.awt.Graphics2D;
java.awt.RenderingHints;
javax.swing.JFrame;
javax.swing.JPanel;
javax.swing.SwingUtilities;
192
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
g2d.setRenderingHints(rh);
Font font = new Font("URW Chancery L", Font.BOLD, 21);
g2d.setFont(font);
g2d.drawString("Not marble, nor the gilded monuments", 20, 30);
g2d.drawString("Of princes, shall outlive this powerful rhyme;", 20, 60);
g2d.drawString("But you shall shine more bright in these contents",
20, 90);
g2d.drawString("Than unswept stone, besmear'd with sluttish time.",
20, 120);
g2d.drawString("When wasteful war shall statues overturn,", 20, 150);
g2d.drawString("And broils root out the work of masonry,", 20, 180);
g2d.drawString("Nor Mars his sword, nor war's quick "
+ "fire shall burn", 20, 210);
g2d.drawString("The living record of your memory.", 20, 240);
g2d.drawString("'Gainst death, and all oblivious enmity", 20, 270);
g2d.drawString("Shall you pace forth; your praise shall still "
+ "find room", 20, 300);
g2d.drawString("Even in the eyes of all posterity", 20, 330);
g2d.drawString("That wear this world out to the ending doom.", 20, 360);
g2d.drawString("So, till the judgment that yourself arise,", 20, 390);
g2d.drawString("You live in this, and dwell in lovers' eyes.", 20, 420);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
doDrawing(g);
}
}
public class DrawingText extends JFrame {
public DrawingText() {
initUI();
}
public final void initUI() {
DrawPanel dpnl = new DrawPanel();
add(dpnl);
setSize(500, 470);
setTitle("Sonnet55");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
193
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
DrawingText ex = new DrawingText();
ex.setVisible(true);
}
});
}
}
Images
On of the most important capabililies of a toolkit is the ability to
display images. An image is an array of pixels. Each pixel
represents a colour at a given position. We can use components
likeJLabel to display an image, or we can draw it using the Java
2D API.
package com.zetcode;
import
import
import
import
import
import
java.awt.Dimension;
java.awt.Graphics;
java.awt.Graphics2D;
java.awt.Image;
javax.swing.ImageIcon;
javax.swing.JFrame;
194
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
class DrawPanel extends JPanel {
Image img;
public DrawPanel() {
loadImage();
Dimension dm = new Dimension(img.getWidth(null), img.getHeight(null));
setPreferredSize(dm);
}
private void loadImage() {
img = new ImageIcon("slanec.png").getImage();
}
private void doDrawing(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(img, 0, 0, null);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
doDrawing(g);
}
}
public class ImageExample extends JFrame {
public ImageExample() {
initUI();
}
public final void initUI() {
DrawPanel dpnl = new DrawPanel();
add(dpnl);
setTitle("Image");
pack();
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
195
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
@Override
public void run() {
ImageExample ex = new ImageExample();
ex.setVisible(true);
}
});
}
}
This example will draw an image on the panel. The image will
fit the JFrame window.
public DrawPanel() {
loadImage();
Dimension dm = new Dimension(img.getWidth(null), img.getHeight(null));
setPreferredSize(dm);
}
In
the
constructor
of
the DrawPanel class,
we
call
the loadImage() method. We determine the image dimensions and
set the preffered size of the panel component. This will together
with the pack()method display the image to fit exactly the
window.
private void loadImage() {
img = new ImageIcon("slanec.png").getImage();
}
drawImage()
method.
Painting in Swing
Swing's painting system is able to render vector graphics,
images, and outline font-based text. Painting is needed in
196
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
2D Vector Graphics
There are two different computer graphics. Vector and raster
graphics. Raster graphics represents images as a collection of
pixels. Vector graphics is the use of geometrical primitives such
as points, lines, curves or polygons to represent images. These
primitives are created using mathematical equations.
Both types of computer graphics have advantages and
disadvantages. The advantages of vector graphics over raster
are:
smaller size
Types of primitives
points
lines
polylines
polygons
circles
197
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
ellipses
Splines
Points
The most simple graphics primitive is point. It is a single dot on
the window. There is no method to draw a point in Swing. To
draw a point, we use the drawLine() method. We use one point
twice.
package com.zetcode;
import
import
import
import
import
import
import
import
import
java.awt.Color;
java.awt.Dimension;
java.awt.Graphics;
java.awt.Graphics2D;
java.awt.Insets;
java.util.Random;
javax.swing.JFrame;
javax.swing.JPanel;
javax.swing.SwingUtilities;
198
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
super.paintComponent(g);
doDrawing(g);
}
}
public class PointsExample extends JFrame {
public PointsExample() {
initUI();
}
public final void initUI() {
DrawPanel dpnl = new DrawPanel();
add(dpnl);
setSize(250, 200);
setTitle("Points");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
PointsExample ex = new PointsExample();
ex.setVisible(true);
}
});
}
}
199
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Graphics2D
object.
g2d.setColor(Color.blue);
Figure: Points
200
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Lines
A line is a simple graphics primitive. It is drawn using two
points.
package com.zetcode;
import
import
import
import
import
import
java.awt.BasicStroke;
java.awt.Graphics;
java.awt.Graphics2D;
javax.swing.JFrame;
javax.swing.JPanel;
javax.swing.SwingUtilities;
dash1
dash2
dash3
dash4
=
=
=
=
{2f,
{1f,
{4f,
{4f,
0f,
1f,
0f,
4f,
2f};
1f};
2f};
1f};
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
doDrawing(g);
}
}
public class LinesExample extends JFrame {
public LinesExample() {
initUI();
}
public final void initUI() {
DrawPanel dpnl = new DrawPanel();
add(dpnl);
setSize(280, 270);
setTitle("Lines");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
LinesExample ex = new LinesExample();
ex.setVisible(true);
}
});
}
}
In the example, we draw five lines. The first line is drawn using
the default values. Other will have a different stroke. The stroke
is created using the BasicStroke class. It defines a basic set of
rendering attributes for the outlines of graphics primitives.
float[] dash1 = { 2f, 0f, 2f };
This code creates a stroke. The stroke defines the line width,
end caps, line joins, miter limit, dash and the dash phase.
202
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Figure: Lines
Rectangles
To draw rectangles, we use the drawRect() method. To fill
rectangles with the current color, we use the fillRect() method.
package com.zetcode;
import
import
import
import
import
import
java.awt.Color;
java.awt.Graphics;
java.awt.Graphics2D;
javax.swing.JFrame;
javax.swing.JPanel;
javax.swing.SwingUtilities;
203
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
g2d.setColor(new Color(42, 179, 231));
g2d.fillRect(130, 15, 90, 60);
g2d.setColor(new Color(70, 67, 123));
g2d.fillRect(250, 15, 90, 60);
g2d.setColor(new Color(130, 100, 84));
g2d.fillRect(10, 105, 90, 60);
g2d.setColor(new Color(252, 211, 61));
g2d.fillRect(130, 105, 90, 60);
g2d.setColor(new Color(241, 98, 69));
g2d.fillRect(250, 105, 90, 60);
g2d.setColor(new Color(217, 146, 54));
g2d.fillRect(10, 195, 90, 60);
g2d.setColor(new Color(63, 121, 186));
g2d.fillRect(130, 195, 90, 60);
g2d.setColor(new Color(31, 21, 1));
g2d.fillRect(250, 195, 90, 60);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
doDrawing(g);
}
}
public class RectanglesExample extends JFrame {
public RectanglesExample() {
initUI();
}
public final void initUI() {
DrawPanel dpnl = new DrawPanel();
add(dpnl);
setSize(360, 300);
setTitle("Rectangles");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
204
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
public void run() {
RectanglesExample ex = new RectanglesExample();
ex.setVisible(true);
}
});
}
}
fillRect()
method.
Figure: Rectangles
Textures
A texture is a bitmap image applied to a shape. To work with
textures in Java 2D, we use theTexturePaint class.
package com.zetcode;
205
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
import
import
import
import
import
java.awt.Graphics;
java.awt.Graphics2D;
java.awt.Rectangle;
java.awt.TexturePaint;
java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
import
import
import
import
import
java.io.IOException;
java.util.logging.Logger;
java.util.logging.Level;
javax.imageio.ImageIO;
javax.swing.SwingUtilities;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
We create a
TexturePaint
g2d.setPaint(slatetp);
g2d.fillRect(10, 15, 90, 60);
Figure: Textures
Gradients
In computer graphics, gradient is a smooth blending of shades
from light to dark or from one colour to another. In 2D drawing
programs and paint programs, gradients are used to create
colourful backgrounds and special effects as well as to simulate
lights and shadows. (answers.com)
package com.zetcode;
import
import
import
import
import
import
import
java.awt.Color;
java.awt.GradientPaint;
java.awt.Graphics;
java.awt.Graphics2D;
javax.swing.JFrame;
javax.swing.JPanel;
javax.swing.SwingUtilities;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
g2d.fillRect(20, 80, 300, 40);
GradientPaint gp3 = new GradientPaint(5, 25,
Color.green, 2, 2, Color.black, true);
g2d.setPaint(gp3);
g2d.fillRect(20, 140, 300, 40);
GradientPaint gp4 = new GradientPaint(25, 25,
Color.blue, 15, 25, Color.black, true);
g2d.setPaint(gp4);
g2d.fillRect(20, 200, 300, 40);
GradientPaint gp5 = new GradientPaint(0, 0,
Color.orange, 0, 20, Color.black, true);
g2d.setPaint(gp5);
g2d.fillRect(20, 260, 300, 40);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
doDrawing(g);
}
}
public class GradientsExample extends JFrame {
public GradientsExample() {
initUI();
}
public final void initUI() {
DrawPanel dpnl = new DrawPanel();
add(dpnl);
setSize(350, 350);
setTitle("Gradients");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
GradientsExample ex = new GradientsExample();
ex.setVisible(true);
209
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
}
});
}
}
setPaint()
method.
Figure: Gradients
Drawing text
Drawing is done with the drawString() method. We specify the
string we want to draw and the position of the text on the
window area.
package com.zetcode;
import java.awt.Font;
210
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
import
import
import
import
import
import
java.awt.Graphics;
java.awt.Graphics2D;
java.awt.RenderingHints;
javax.swing.JFrame;
javax.swing.JPanel;
javax.swing.SwingUtilities;
211
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
public class DrawingText extends JFrame {
public DrawingText() {
initUI();
}
public final void initUI() {
DrawPanel dpnl = new DrawPanel();
add(dpnl);
setSize(500, 470);
setTitle("Sonnet55");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
DrawingText ex = new DrawingText();
ex.setVisible(true);
}
});
}
}
Images
212
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
java.awt.Dimension;
java.awt.Graphics;
java.awt.Graphics2D;
java.awt.Image;
javax.swing.ImageIcon;
javax.swing.JFrame;
javax.swing.JPanel;
javax.swing.SwingUtilities;
213
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
initUI();
}
public final void initUI() {
DrawPanel dpnl = new DrawPanel();
add(dpnl);
setTitle("Image");
pack();
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
ImageExample ex = new ImageExample();
ex.setVisible(true);
}
});
}
}
This example will draw an image on the panel. The image will
fit the JFrame window.
public DrawPanel() {
loadImage();
Dimension dm = new Dimension(img.getWidth(null), img.getHeight(null));
setPreferredSize(dm);
}
In
the
constructor
of
the DrawPanel class,
we
call
the loadImage() method. We determine the image dimensions and
set the preffered size of the panel component. This will together
with the pack()method display the image to fit exactly the
window.
private void loadImage() {
img = new ImageIcon("slanec.png").getImage();
}
214
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
g2d.drawImage(this.img, 0, 0, null);
drawImage()
method.
Resizable
Swing
component
in
Java
Resizable component
Resizable components are often used when creating charts or
diagrams. A common resizable component is a chart in a
spreadsheet application. The chart can be moved over a table
widget of the application and resized.
In order to create a component that can be freely dragged over
a panel, we use a panel with absolute positioning enabled. In
our example, we will create a component that we can freely
move over a parent window and resize.
Eight small rectangles are drawn on the border of our resizable
component when it has the focus. The rectangles serve as
dragging points, where we can draw the component and start
resizing. The following example is based on an example
from this blog.
ResizableComponentEx.java
package com.zetcode;
import java.awt.Color;
215
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
import
import
import
import
import
java.awt.EventQueue;
java.awt.event.MouseAdapter;
java.awt.event.MouseEvent;
javax.swing.JFrame;
javax.swing.JPanel;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
ResizableComponentEx
java.awt.Color;
java.awt.Component;
java.awt.Cursor;
java.awt.Graphics;
java.awt.Insets;
java.awt.Rectangle;
java.awt.event.MouseEvent;
javax.swing.SwingConstants;
javax.swing.border.Border;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Cursor.SW_RESIZE_CURSOR, Cursor.SE_RESIZE_CURSOR
};
public ResizableBorder(int dist) {
this.dist = dist;
}
@Override
public Insets getBorderInsets(Component component) {
return new Insets(dist, dist, dist, dist);
}
@Override
public boolean isBorderOpaque() {
return false;
}
@Override
public void paintBorder(Component component, Graphics g, int x, int y,
int w, int h) {
g.setColor(Color.black);
g.drawRect(x + dist / 2, y + dist / 2, w - dist, h - dist);
if (component.hasFocus()) {
for (int i = 0; i < locations.length; i++) {
Rectangle rect = getRectangle(x, y, w, h, locations[i]);
g.setColor(Color.WHITE);
g.fillRect(rect.x, rect.y, rect.width - 1, rect.height - 1);
g.setColor(Color.BLACK);
g.drawRect(rect.x, rect.y, rect.width - 1, rect.height - 1);
}
}
}
private Rectangle getRectangle(int x, int y, int w, int h, int location) {
switch (location) {
case SwingConstants.NORTH:
return new Rectangle(x + w / 2 - dist / 2, y, dist, dist);
case SwingConstants.SOUTH:
return new Rectangle(x + w / 2 - dist / 2, y + h - dist, dist,
dist);
case SwingConstants.WEST:
return new Rectangle(x, y + h / 2 - dist / 2, dist, dist);
case SwingConstants.EAST:
return new Rectangle(x + w - dist, y + h / 2 - dist / 2, dist,
dist);
case SwingConstants.NORTH_WEST:
return new Rectangle(x, y, dist, dist);
case SwingConstants.NORTH_EAST:
return new Rectangle(x + w - dist, y, dist, dist);
218
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
case SwingConstants.SOUTH_WEST:
return new Rectangle(x, y + h - dist, dist, dist);
case SwingConstants.SOUTH_EAST:
return new Rectangle(x + w - dist, y + h - dist, dist, dist);
}
return null;
}
public int getCursor(MouseEvent me) {
Component c = me.getComponent();
int w = c.getWidth();
int h = c.getHeight();
for (int i = 0; i < locations.length; i++) {
Rectangle rect = getRectangle(0, 0, w, h, locations[i]);
if (rect.contains(me.getPoint())) {
return cursors[i];
}
}
return Cursor.MOVE_CURSOR;
}
}
int locations[] = {
SwingConstants.NORTH, SwingConstants.SOUTH, SwingConstants.WEST,
SwingConstants.EAST, SwingConstants.NORTH_WEST,
SwingConstants.NORTH_EAST, SwingConstants.SOUTH_WEST,
SwingConstants.SOUTH_EAST
};
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
g.fillRect(rect.x, rect.y, rect.width - 1, rect.height - 1);
g.setColor(Color.BLACK);
g.drawRect(rect.x, rect.y, rect.width - 1, rect.height - 1);
}
}
The eight rectangles are drawn only in case that the resizable
component currently has focus.
private Rectangle getRectangle(int x, int y, int w, int h, int location) {
switch (location) {
case SwingConstants.NORTH:
return new Rectangle(x + w / 2 - dist / 2, y, dist, dist);
case SwingConstants.SOUTH:
return new Rectangle(x + w / 2 - dist / 2, y + h - dist, dist,
dist);
...
}
The
getRectangle()
The getCursor() method gets the cursor type for the grab point in
question.
Resizable.java
package com.zetcode;
import
import
import
import
import
import
import
import
java.awt.BorderLayout;
java.awt.Component;
java.awt.Cursor;
java.awt.Point;
java.awt.Rectangle;
java.awt.event.MouseEvent;
javax.swing.JComponent;
javax.swing.event.MouseInputAdapter;
220
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
import javax.swing.event.MouseInputListener;
public class Resizable extends JComponent {
public Resizable(Component comp) {
this(comp, new ResizableBorder(8));
}
public Resizable(Component comp, ResizableBorder border) {
setLayout(new BorderLayout());
add(comp);
addMouseListener(resizeListener);
addMouseMotionListener(resizeListener);
setBorder(border);
}
private void resize() {
if (getParent() != null) {
((JComponent) getParent()).revalidate();
}
}
MouseInputListener resizeListener = new MouseInputAdapter() {
@Override
public void mouseMoved(MouseEvent me) {
if (hasFocus()) {
ResizableBorder border = (ResizableBorder) getBorder();
setCursor(Cursor.getPredefinedCursor(border.getCursor(me)));
}
}
@Override
public void mouseExited(MouseEvent mouseEvent) {
setCursor(Cursor.getDefaultCursor());
}
private int cursor;
private Point startPos = null;
@Override
public void mousePressed(MouseEvent me) {
ResizableBorder border = (ResizableBorder) getBorder();
cursor = border.getCursor(me);
startPos = me.getPoint();
requestFocus();
repaint();
}
@Override
221
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
public void mouseDragged(MouseEvent me) {
if (startPos != null) {
int
int
int
int
x = getX();
y = getY();
w = getWidth();
h = getHeight();
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
startPos = new Point(me.getX(), startPos.y);
resize();
}
break;
case Cursor.SW_RESIZE_CURSOR:
if (!(w - dx < 50) && !(h + dy < 50)) {
setBounds(x + dx, y, w - dx, h + dy);
startPos = new Point(startPos.x, me.getY());
resize();
}
break;
case Cursor.SE_RESIZE_CURSOR:
if (!(w + dx < 50) && !(h + dy < 50)) {
setBounds(x, y, w + dx, h + dy);
startPos = me.getPoint();
resize();
}
break;
case Cursor.MOVE_CURSOR:
Rectangle bounds = getBounds();
bounds.translate(dx, dy);
setBounds(bounds);
resize();
}
setCursor(Cursor.getPredefinedCursor(cursor));
}
}
@Override
public void mouseReleased(MouseEvent mouseEvent) {
startPos = null;
}
};
}
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
MouseInputListener resizeListener = new MouseInputAdapter() {
@Override
public void mouseMoved(MouseEvent me) {
if (hasFocus()) {
ResizableBorder border = (ResizableBorder) getBorder();
setCursor(Cursor.getPredefinedCursor(border.getCursor(me)));
}
}
...
}
We change the cursor type, when we hover the cursor over the
grab points. The cursor type changes only if the component has
focus.
@Override
public void mousePressed(MouseEvent me) {
ResizableBorder border = (ResizableBorder) getBorder();
cursor = border.getCursor(me);
startPos = me.getPoint();
requestFocus();
repaint();
}
x = getX();
y = getY();
w = getWidth();
h = getHeight();
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
eventually
hide
the
component.
relocates and resizes the component.
The
setBounds()
method
Puzzle
The goal of this little game is to form a picture. Buttons
containing images are moved by clicking on them. Only buttons
adjacent to the empty button can be moved.
package com.zetcode;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
225
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
java.awt.Graphics2D;
java.awt.GridLayout;
java.awt.Image;
java.awt.Point;
java.awt.event.ActionEvent;
java.awt.event.MouseAdapter;
java.awt.event.MouseEvent;
java.awt.image.BufferedImage;
java.awt.image.CropImageFilter;
java.awt.image.FilteredImageSource;
java.io.File;
java.io.IOException;
java.util.ArrayList;
java.util.Collections;
java.util.List;
java.util.logging.Level;
java.util.logging.Logger;
javax.imageio.ImageIO;
javax.swing.AbstractAction;
javax.swing.BorderFactory;
javax.swing.ImageIcon;
javax.swing.JButton;
javax.swing.JComponent;
javax.swing.JFrame;
javax.swing.JOptionPane;
javax.swing.JPanel;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
public void mouseEntered(MouseEvent e) {
setBorder(BorderFactory.createLineBorder(Color.yellow));
}
@Override
public void mouseExited(MouseEvent e) {
setBorder(BorderFactory.createLineBorder(Color.gray));
}
});
}
public void setLastButton() {
isLastButton = true;
}
public boolean isLastButton() {
return isLastButton;
}
}
public class PuzzleEx extends JFrame {
private JPanel panel;
private BufferedImage source;
private ArrayList<MyButton> buttons;
ArrayList<Point> solution = new ArrayList();
private
private
private
private
private
Image image;
MyButton lastButton;
int width, height;
final int DESIRED_WIDTH = 300;
BufferedImage resized;
public PuzzleEx() {
initUI();
}
private void initUI() {
solution.add(new
solution.add(new
solution.add(new
solution.add(new
solution.add(new
solution.add(new
solution.add(new
solution.add(new
solution.add(new
solution.add(new
Point(0,
Point(0,
Point(0,
Point(1,
Point(1,
Point(1,
Point(2,
Point(2,
Point(2,
Point(3,
0));
1));
2));
0));
1));
2));
0));
1));
2));
0));
227
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
solution.add(new Point(3, 1));
solution.add(new Point(3, 2));
buttons = new ArrayList();
panel = new JPanel();
panel.setBorder(BorderFactory.createLineBorder(Color.gray));
panel.setLayout(new GridLayout(4, 3, 0, 0));
try {
source = loadImage();
int h = getNewHeight(source.getWidth(), source.getHeight());
resized = resizeImage(source, DESIRED_WIDTH, h,
BufferedImage.TYPE_INT_ARGB);
} catch (IOException ex) {
Logger.getLogger(PuzzleEx.class.getName()).log(
Level.SEVERE, null, ex);
}
width = resized.getWidth(null);
height = resized.getHeight(null);
add(panel, BorderLayout.CENTER);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 3; j++) {
image = createImage(new FilteredImageSource(resized.getSource(),
new CropImageFilter(j * width / 3, i * height / 4,
(width / 3), height / 4)));
MyButton button = new MyButton(image);
button.putClientProperty("position", new Point(i, j));
if (i == 3 && j == 2) {
lastButton = new MyButton();
lastButton.setBorderPainted(false);
lastButton.setContentAreaFilled(false);
lastButton.setLastButton();
lastButton.putClientProperty("position", new Point(i, j));
} else {
buttons.add(button);
}
}
}
Collections.shuffle(buttons);
buttons.add(lastButton);
for (int i = 0; i < 12; i++) {
MyButton btn = buttons.get(i);
228
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
panel.add(btn);
btn.setBorder(BorderFactory.createLineBorder(Color.gray));
btn.addActionListener(new ClickAction());
}
pack();
setTitle("Puzzle");
setResizable(false);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private int getNewHeight(int w, int h) {
double ratio = DESIRED_WIDTH / (double) w;
int newHeight = (int) (h * ratio);
return newHeight;
}
private BufferedImage loadImage() throws IOException {
BufferedImage bimg = ImageIO.read(new File("icesid.jpg"));
return bimg;
}
private BufferedImage resizeImage(BufferedImage originalImage, int width,
int height, int type) throws IOException {
BufferedImage resizedImage = new BufferedImage(width, height, type);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, width, height, null);
g.dispose();
return resizedImage;
}
private class ClickAction extends AbstractAction {
@Override
public void actionPerformed(ActionEvent e) {
checkButton(e);
checkSolution();
}
private void checkButton(ActionEvent e) {
int lidx = 0;
for (MyButton button : buttons) {
if (button.isLastButton()) {
lidx = buttons.indexOf(button);
}
229
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
}
JButton button = (JButton) e.getSource();
int bidx = buttons.indexOf(button);
if ((bidx - 1 == lidx) || (bidx + 1 == lidx)
|| (bidx - 3 == lidx) || (bidx + 3 == lidx)) {
Collections.swap(buttons, bidx, lidx);
updateButtons();
}
}
private void updateButtons() {
panel.removeAll();
for (JComponent btn : buttons) {
panel.add(btn);
}
panel.validate();
}
}
private void checkSolution() {
ArrayList<Point> current = new ArrayList();
for (JComponent btn : buttons) {
current.add((Point) btn.getClientProperty("position"));
}
if (compareList(solution, current)) {
JOptionPane.showMessageDialog(panel, "Finished",
"Congratulation", JOptionPane.INFORMATION_MESSAGE);
}
}
public static boolean compareList(List ls1, List ls2) {
return ls1.toString().contentEquals(ls2.toString());
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
PuzzleEx puzzle = new PuzzleEx();
puzzle.setVisible(true);
}
});
230
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
}
}
Point(0,
Point(0,
Point(0,
Point(1,
0));
1));
2));
0));
The solution array list stores the correct order of buttons which
forms the image. Each button is identified by one Point.
231
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
panel.setLayout(new GridLayout(4, 3, 0, 0));
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
}
All the components from the buttons list are placed on the panel.
We create some gray border around the buttons and add a click
action listener.
private int getNewHeight(int w, int h) {
double ratio = DESIRED_WIDTH / (double) w;
int newHeight = (int) (h * ratio);
return newHeight;
}
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
JButton button = (JButton) e.getSource();
int bidx = buttons.indexOf(button);
if ((bidx - 1 == lidx) || (bidx + 1 == lidx)
|| (bidx - 3 == lidx) || (bidx + 3 == lidx)) {
Collections.swap(buttons, bidx, lidx);
updateButtons();
}
}
The updateButtons() method maps the list to the panel's grid. First,
all components are removed with the removeAll() method. A for
loop is used to go trough the buttons list to add the reordered
buttons back to the panel's layout manager. Finally,
the validate() method implements the new layout.
private void checkSolution() {
ArrayList<Point> current = new ArrayList();
for (JComponent btn : buttons) {
current.add((Point) btn.getClientProperty("position"));
}
if (compareList(solution, current)) {
JOptionPane.showMessageDialog(panel, "Finished",
"Congratulation", JOptionPane.INFORMATION_MESSAGE);
}
}
234
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Figure: Puzzle
Tetris
In this chapter, we will create a Tetris game clone in Java Swing.
Tetris
The Tetris game is one of the most popular computer games
ever created. The original game was designed and programmed
by a Russian programmer Alexey Pajitnov in 1985. Since then,
Tetris is available on almost every computer platform in lots of
variations.
Tetris is called a falling block puzzle game. In this game, we
have seven different shapes calledtetrominoes: S-shape, Zshape, T-shape, L-shape, Line-shape, MirroredL-shape, and a
Square-shape. Each of these shapes is formed with four
235
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
squares. The shapes are falling down the board. The object of
the Tetris game is to move and rotate the shapes so that they
fit as much as possible. If we manage to form a row, the row is
destroyed and we score. We play the Tetris game until we top
out.
Figure: Tetrominoes
The development
We do not have images for our Tetris game, we draw the
tetrominoes using Swing drawing API. Behind every computer
game, there is a mathematical model. So it is in Tetris.
Some ideas behind the game.
We use a
Timer
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Tetris.java
package com.zetcode;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class Tetris extends JFrame {
private JLabel statusbar;
public Tetris() {
initUI();
}
private void initUI() {
statusbar = new JLabel(" 0");
add(statusbar, BorderLayout.SOUTH);
Board board = new Board(this);
add(board);
board.start();
setSize(200, 400);
setTitle("Tetris");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
public JLabel getStatusBar() {
return statusbar;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Tetris game = new Tetris();
game.setVisible(true);
}
});
}
}
237
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
The start() method starts the Tetris game. Immediately, after the
window appears on the screen.
Shape.java
package com.zetcode;
import java.util.Random;
public class Shape {
protected enum Tetrominoes { NoShape, ZShape, SShape, LineShape,
TShape, SquareShape, LShape, MirroredLShape };
private Tetrominoes pieceShape;
private int coords[][];
private int[][][] coordsTable;
public Shape() {
coords = new int[4][2];
setShape(Tetrominoes.NoShape);
}
public void setShape(Tetrominoes shape) {
coordsTable = new int[][][] {
{ { 0, 0 }, { 0, 0 }, { 0, 0 },
{ { 0, -1 }, { 0, 0 }, { -1, 0 },
{ { 0, -1 }, { 0, 0 }, { 1, 0 },
{ { 0, -1 }, { 0, 0 }, { 0, 1 },
{ { -1, 0 }, { 0, 0 }, { 1, 0 },
{ { 0, 0 }, { 1, 0 }, { 0, 1 },
{ { -1, -1 }, { 0, -1 }, { 0, 0 },
{ { 1, -1 }, { 0, -1 }, { 0, 0 },
};
{ 0, 0 } },
{ -1, 1 } },
{ 1, 1 } },
{ 0, 2 } },
{ 0, 1 } },
{ 1, 1 } },
{ 0, 1 } },
{ 0, 1 } }
238
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
pieceShape = shape;
}
private void setX(int index, int x) { coords[index][0] = x; }
private void setY(int index, int y) { coords[index][1] = y; }
public int x(int index) { return coords[index][0]; }
public int y(int index) { return coords[index][1]; }
public Tetrominoes getShape() { return pieceShape; }
public void setRandomShape() {
Random r = new Random();
int x = Math.abs(r.nextInt()) % 7 + 1;
Tetrominoes[] values = Tetrominoes.values();
setShape(values[x]);
}
public int minX() {
int m = coords[0][0];
for (int i=0; i < 4; i++) {
m = Math.min(m, coords[i][0]);
}
return m;
}
public int minY() {
int m = coords[0][1];
for (int i=0; i < 4; i++) {
m = Math.min(m, coords[i][1]);
}
return m;
}
public Shape rotateLeft() {
if (pieceShape == Tetrominoes.SquareShape)
return this;
Shape result = new Shape();
result.pieceShape = pieceShape;
for (int i = 0; i < 4; ++i) {
result.setX(i, y(i));
239
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
result.setY(i, -x(i));
}
return result;
}
public Shape rotateRight() {
if (pieceShape == Tetrominoes.SquareShape)
return this;
Shape result = new Shape();
result.pieceShape = pieceShape;
for (int i = 0; i < 4; ++i) {
result.setX(i, -y(i));
result.setY(i, x(i));
}
return result;
}
}
The
Shape
The Tetrominoes enum holds all seven Tetris shapes. Plus the
empty shape called here NoShape.
public Shape() {
coords = new int[4][2];
setShape(Tetrominoes.NoShape);
}
{ 0, 0 } },
{ -1, 1 } },
{ 1, 1 } },
{ 0, 2 } },
{ 0, 1 } },
{ 1, 1 } },
{ 0, 1 } },
{ 0, 1 } }
240
coords
array holds
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
};
Figure: Coordinates
public Shape rotateLeft() {
if (pieceShape == Tetrominoes.SquareShape)
return this;
Shape result = new Shape();
241
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
result.pieceShape = pieceShape;
for (int i = 0; i < 4; ++i) {
result.setX(i, y(i));
result.setY(i, -x(i));
}
return result;
}
This code rotates the piece to the left. The square does not
have to be rotated. That's why we simply return the reference
to the current object. Looking at the previous image will help to
understand the rotation.
Board.java
package com.zetcode;
import
import
import
import
import
import
import
import
import
import
java.awt.Color;
java.awt.Dimension;
java.awt.Graphics;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
java.awt.event.KeyAdapter;
java.awt.event.KeyEvent;
javax.swing.JLabel;
javax.swing.JPanel;
javax.swing.Timer;
import com.zetcode.Shape.Tetrominoes;
public class Board extends JPanel
implements ActionListener {
private final int BoardWidth = 10;
private final int BoardHeight = 22;
private
private
private
private
private
private
private
private
private
private
Timer timer;
boolean isFallingFinished = false;
boolean isStarted = false;
boolean isPaused = false;
int numLinesRemoved = 0;
int curX = 0;
int curY = 0;
JLabel statusbar;
Shape curPiece;
Tetrominoes[] board;
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
initBoard(parent);
}
private void initBoard(Tetris parent) {
setFocusable(true);
curPiece = new Shape();
timer = new Timer(400, this);
timer.start();
statusbar = parent.getStatusBar();
board = new Tetrominoes[BoardWidth * BoardHeight];
addKeyListener(new TAdapter());
clearBoard();
}
@Override
public void actionPerformed(ActionEvent e) {
if (isFallingFinished) {
isFallingFinished = false;
newPiece();
} else {
oneLineDown();
}
}
private int squareWidth() { return (int) getSize().getWidth() / BoardWidth; }
private int squareHeight() { return (int) getSize().getHeight() / BoardHeight; }
private Tetrominoes shapeAt(int x, int y) { return board[(y * BoardWidth) +
x]; }
public void start() {
if (isPaused)
return;
isStarted = true;
isFallingFinished = false;
numLinesRemoved = 0;
clearBoard();
newPiece();
timer.start();
}
private void pause() {
if (!isStarted)
243
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
return;
isPaused = !isPaused;
if (isPaused) {
timer.stop();
statusbar.setText("paused");
} else {
timer.start();
statusbar.setText(String.valueOf(numLinesRemoved));
}
repaint();
}
private void doDrawing(Graphics g) {
Dimension size = getSize();
int boardTop = (int) size.getHeight() - BoardHeight * squareHeight();
for (int i = 0; i < BoardHeight; ++i) {
for (int j = 0; j < BoardWidth; ++j) {
Tetrominoes shape = shapeAt(j, BoardHeight - i - 1);
if (shape != Tetrominoes.NoShape)
drawSquare(g, 0 + j * squareWidth(),
boardTop + i * squareHeight(), shape);
}
}
if (curPiece.getShape() != Tetrominoes.NoShape) {
for (int i = 0; i < 4; ++i) {
int x = curX + curPiece.x(i);
int y = curY - curPiece.y(i);
drawSquare(g, 0 + x * squareWidth(),
boardTop + (BoardHeight - y - 1) * squareHeight(),
curPiece.getShape());
}
}
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
doDrawing(g);
}
244
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
isStarted = false;
statusbar.setText("game over");
}
}
private boolean tryMove(Shape newPiece, int newX, int newY) {
for (int i = 0; i < 4; ++i) {
int x = newX + newPiece.x(i);
int y = newY - newPiece.y(i);
if (x < 0 || x >= BoardWidth || y < 0 || y >= BoardHeight)
return false;
if (shapeAt(x, y) != Tetrominoes.NoShape)
return false;
}
curPiece = newPiece;
curX = newX;
curY = newY;
repaint();
return true;
}
private void removeFullLines() {
int numFullLines = 0;
for (int i = BoardHeight - 1; i >= 0; --i) {
boolean lineIsFull = true;
for (int j = 0; j < BoardWidth; ++j) {
if (shapeAt(j, i) == Tetrominoes.NoShape) {
lineIsFull = false;
break;
}
}
if (lineIsFull) {
++numFullLines;
for (int k = i; k < BoardHeight - 1; ++k) {
for (int j = 0; j < BoardWidth; ++j)
board[(k * BoardWidth) + j] = shapeAt(j, k + 1);
}
}
}
if (numFullLines > 0) {
246
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
numLinesRemoved += numFullLines;
statusbar.setText(String.valueOf(numLinesRemoved));
isFallingFinished = true;
curPiece.setShape(Tetrominoes.NoShape);
repaint();
}
}
private void drawSquare(Graphics g, int x, int y, Tetrominoes shape) {
Color colors[] = { new Color(0, 0,
new Color(102, 204, 102), new
new Color(204, 204, 102), new
new Color(102, 204, 204), new
};
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
case KeyEvent.VK_LEFT:
tryMove(curPiece, curX - 1, curY);
break;
case KeyEvent.VK_RIGHT:
tryMove(curPiece, curX + 1, curY);
break;
case KeyEvent.VK_DOWN:
tryMove(curPiece.rotateRight(), curX, curY);
break;
case KeyEvent.VK_UP:
tryMove(curPiece.rotateLeft(), curX, curY);
break;
case KeyEvent.VK_SPACE:
dropDown();
break;
case 'd':
oneLineDown();
break;
case 'D':
oneLineDown();
break;
}
}
}
}
Board.java
We
initialize
some
important
variables.
The isFallingFinished variable determines, if the Tetris shape has
finished falling and we then need to create a new shape.
The numLinesRemoved counts the number of lines, we have
248
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
removed so far. The curX and curY variables determine the actual
position of the falling Tetris shape.
setFocusable(true);
@Override
public void actionPerformed(ActionEvent e) {
if (isFallingFinished) {
isFallingFinished = false;
newPiece();
} else {
oneLineDown();
}
}
249
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
250
NoShapes.
This
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
for (int i = 0; i < 4; ++i) {
int x = curX + curPiece.x(i);
int y = curY - curPiece.y(i);
board[(y * BoardWidth) + x] = curPiece.getShape();
}
removeFullLines();
if (!isFallingFinished)
newPiece();
}
The newPiece() method creates a new Tetris piece. The piece gets
a
new
random
shape.
Then
we
compute
the
initial curX and curY values. If we cannot move to the initial
positions, the game is over. We top out. The timer is stopped.
We put game over string on the statusbar.
private boolean tryMove(Shape newPiece, int newX, int newY) {
for (int i = 0; i < 4; ++i) {
int x = newX + newPiece.x(i);
int y = newY - newPiece.y(i);
251
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
if (x < 0 || x >= BoardWidth || y < 0 || y >= BoardHeight)
return false;
if (shapeAt(x, y) != Tetrominoes.NoShape)
return false;
}
curPiece = newPiece;
curX = newX;
curY = newY;
repaint();
return true;
}
The tryMove() method tries to move the Tetris piece. The method
returns false if it has reached the board boundaries or it is
adjacent to the already fallen Tetris pieces.
int numFullLines = 0;
for (int i = BoardHeight - 1; i >= 0; --i) {
boolean lineIsFull = true;
for (int j = 0; j < BoardWidth; ++j) {
if (shapeAt(j, i) == Tetrominoes.NoShape) {
lineIsFull = false;
break;
}
}
if (lineIsFull) {
++numFullLines;
for (int k = i; k < BoardHeight - 1; ++k) {
for (int j = 0; j < BoardWidth; ++j)
board[(k * BoardWidth) + j] = shapeAt(j, k + 1);
}
}
}
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
The left and top sides of a square are drawn with a brighter
color. Similarly, the bottom and right sides are drawn with
darker colours. This is to simulate a 3D edge.
We control the game with a keyboard. The control mechanism
is implemented with a KeyAdapter. This is an inner class that
overrides the keyPressed() method.
case KeyEvent.VK_LEFT:
tryMove(curPiece, curX - 1, curY);
break;
If we press the left arrow key, we try to move the falling piece
one square to the left.
Figure: Tetris
253
Ngun: Internet.
Ngi su tm: Thn Triu @Pro.
254