It's all about Java: GUI
Showing posts with label GUI. Show all posts
Showing posts with label GUI. Show all posts

Wednesday, 6 January 2021

Java - Swing custom components - Rounded JButton

Unlike AWT, Java Swing tool kit provides feasibilty to create custom components and containers.

To understand Java GUI toolkits more clearly, please read my other articles on Swing and AWT. 

In this article I focus more on building custom components.

Let us see how to create simple Rounded JButton. The below program demonstrates How rounded JButton can be created and added to a JFrame.

 

Program:


import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class RoundedJButton extends JButton {

/**
*/
private static final long serialVersionUID = 1L;

public RoundedJButton(String title) {
super(title);
Dimension size = getPreferredSize();
size.width = size.height = Math.max(size.width, size.height);
setPreferredSize(size);

setContentAreaFilled(false);
}

@Override
protected void paintComponent(Graphics g) {
if (getModel().isArmed()) {
g.setColor(Color.lightGray);
} else {
g.setColor(getBackground());
}
g.fillOval(0, 0, getSize().width - 1, getSize().height - 1);

super.paintComponent(g);
}

@Override
protected void paintBorder(Graphics g) {
g.setColor(getForeground());
g.drawOval(0, 0, getSize().width - 1, getSize().height - 1);
}

Shape shape;

@Override
public boolean contains(int x, int y) {
if (shape == null || !shape.getBounds().equals(getBounds())) {
shape = new Ellipse2D.Float(0, 0, getWidth(), getHeight());
}
return shape.contains(x, y);
}

public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {

JFrame frame = new JFrame();
frame.setTitle("It's all about Java...");
frame.setSize(150, 150);
GridLayout layout = new GridLayout();
layout.setRows(1);
layout.setHgap(10);
layout.setVgap(10);
frame.setLayout(layout);

JTextField field1 = new JTextField();
field1.setText("This is a textfield!");
frame.getContentPane().add(field1);

RoundedJButton button = new RoundedJButton("Browse");
button.setBackground(Color.gray);
button.setForeground(Color.GREEN);
frame.getContentPane().add(button);

UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
frame.pack();
frame.setVisible(true);
}
});
}
}

There are two parts in the program. First part creates RoundedJButton component by extending JButton. and second part creates JFrame and appends two components. 1. RoundedJButton and 2. JTextField

First Part:


RoundedJButton overrides paintComponent(Graphics g) and paintBorder(Graphics g) to get the circled shape to the Button. 

Second Part:

Second part contains main method which creates JFrame object and adds 2 components to JFrame dialog.

Also applies System look and feel by using following

UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

I will explain clearly about pluggable look and feels also known as PLAF in future articles.

That's all for now!

Happy coding... :) 

Monday, 29 January 2018

Swing JLabel demo with example

This article is continuation of previous post JFrame usage demo. Please read it before continuing.

This post uses the same example code shown in JFrame usage demo with JLabel changes and introduces layout manager BorderLayout.

Layout Manager:

Layout manager is responsible to arrange components on containers. Usually every swing container is created with a default layout manager but can be changed with setLayout() api. For example JFrame uses BorderLayout as default layout amanger.

Java program for JLabel


2   import java.awt.BorderLayout;
3   import java.awt.Color;
4   import java.awt.Font;

6   import javax.swing.JFrame;
7   import javax.swing.JLabel;
8   import javax.swing.SwingUtilities;

10  /**
11   *
12   * Simple class to demonstrate JLabel of swing toolkit
13   *
14   * @author Nagasharath
15   *
16   */
17  public class LabelDemo extends JFrame {
18
19  private final String title = "It's all abt java!...  ";
20
21  private JLabel label;
22
23  /**
24  * set properties of the main window. Title, size of frame and position/location
25  */
26  public LabelDemo() {
27  this.setTitle(title);
28  this.setSize(300, 200);
29  this.setLocationRelativeTo(null);
30  initComponents();
31  }
32
33  /**
34  * instantiates controls controls.
35  *
36  */
37  private void initComponents() {
38  BorderLayout layout = new BorderLayout(20, 10);
39  this.setLayout(layout);
40
41  label = new JLabel("java-gui.blogspot.com");
42  label.setForeground(Color.RED);
43  label.setFont(new Font(Font.MONOSPACED, Font.BOLD, 25));
44  this.getContentPane().add(label, BorderLayout.CENTER);
45  }
46
47  public static void main(String[] args) {
48
49  Runnable r = () -> {
50  LabelDemo demo = new LabelDemo();
51  demo.setVisible(true);
52  };
53  SwingUtilities.invokeLater(r);
54  }
55  }
56


Line 21: Introduced new variable of type JLabel

Line 38 and Line 39: Used BorderLayout as layout manager to arrange label component on JFrame container

Line 41: Instantiated label with a text of String type.

Line 42 and Line 43:  label properties like foreground color, font style, size, type and background etc are specified

Line 44:  Finally added this label to the JFrame using add().

Output:


JFrme with JLabel

Swing: JFrame usage demo

This post helps in understanding usage of JFrame class with an example


Swing toolkit categorizes components into 2 types. They are:

  • Containers
  • Controls

Containers allows Controls to be arranged on them. JPanel, JFrame and JDialog are few which are frequently used.

Controls are components like Buttons, labels, tables etc. These controls are arranged on containers using different layout managers.

All Swing class names starts with J stands for Java which symbolizes swing is pure java! 

Layout Managers:

Layout manager is responsible for laying out controls on containers according to the business requirement. Example layout managers are BorderLayout, GridLayout, GridBagLayout and FlowLayout.

Few points about JFrame:
  • JFrame is considered as a main window of the application.for almost all swing based applications
  • All other controls and containers are created as child components of JFrame
  • JFrama holds special components like  Menu bar, Tool bar etc  

Example program

1 import javax.swing.JFrame;
2 import javax.swing.SwingUtilities;
3
4 /**
5  *
6  * Simple class to demonstrate JFrame container of swing toolkit
7  *
8  * @author Nagasharath
9  *
10 */
11public class FrameDemo extends JFrame {
12
13 private final String title = "It's all abt java!...  ";
14
15 /**
16 * set properties of the main window. Title, size of frame and position/location
17 */
18 public FrameDemo() {
19 this.setTitle(title);
20 this.setSize(300, 200);
21 this.setLocationRelativeTo(null);
22 initComponents();
23 }
24
25 /**
26 * It is used in future articles for instantiating controls like buttons etc.
27 * left empty for now.
28 */
29 private void initComponents() {
30 }
31
32 public static void main(String[] args) {
33
34 Runnable r = () -> {
35 FrameDemo demo = new FrameDemo();
36 demo.setVisible(true);
37 };
38 SwingUtilities.invokeLater(r);
39 }
40}
41


Line 1: Our class FrameDemo extends JFrame hence gets all benefits that JFrame possess    

Line 20: Sets the width 300 and height 200. How ever frame is re sizable at run time

Line 21:  Puts the frame at the center of the desktop monitor

Line 36: Unless call to setVisible(true), frame can not be seen at all.

Line 38: It is always good practice to call setVisible(true) in invokeLater().

Output on Win 10:

The look and feel we see below  is default which is same on all platforms 

This Look and feel can be changed using UIManager class. We see it in coming posts.  

      
JFrame with title


Sunday, 28 January 2018

Java desktop GUI.

Graphical user interface in short GUI makes computer users easy to understand and use the application software comfortably. Almost all modern programming languages allows application developers to develop GUIs.

Java has AWT/Swing as default API as part of Java Foundation classes in short JFC which are shipped with JDK. Hence these toolkits can be used directly in our applications with out adding external libraries like jars to our application's class path. But there are some other toolkits which found useful and industry endorsed in developing GUI.

    •      SWT 
    •      JFaces [Framework for SWT]
    •      Java FX
    •      Swing
    •      AWT

AWT:

Abstract window toolkit is available since java first version. AWT uses native operating system resources like Fonts, colors and components like table, tree, dialogues, windows etc.

Few notable points about AWT:
  • AWT is heavy weight. It uses OS resources
  • There are limited components in AWT precisely only components which are available in native OS. 
  • We can not have a new component according to our business logic need. ex: Tri state checkbox or treetable  
  • AWT behaves differently on different platforms
  • Hence it violates the java Platform independence rule
  • The program GUI developed with AWT looks differently on different OSs. Means on linux it renders linux graphics look and feel and on windows platform it renders windows graphics look and feel.   
  • Provides event model API which also used by Swing toolkit

Swing:

  • Swing was designed and developed keeping all cons in mind that are caused due to using AWT toolkit.
  • First of all "Swing is pure java hence it is platform independent." This statement made many good things possible:
Few notable points about Swing:
  •  Swing is light weight. It does not depend on native OS resources 
  •  Unlike AWT, it is extensible. New custom components can be developed according to program  requirement. 
   NOTE: See swingx library in it's official site.
  •  Swing has Pluggable look-and-feel support in short PLAF.
  •  Drag and Drop api, 2D api, internationalization are few among other included in Swing toolkit.
  •  Netbeans IDE itself is a good example for swing based application used allot now a days.
  •  Few GUI experts noticed that Swing is slow and not quite professional for commercial applications

SWT:

Standard Widget toolkit in short SWT is another toolkit for developing Java Desktop GUI based applications.
Compared to Swing it is faster and consistent in performance and Eclipse IDE itself is an example for SWT based applications.
Eclipse is industry endorsed IDE specifically for java based software development.
This is not shipped with JDK. Please see eclipse.org [official site] for more details.
And there are Integrated development environments in short IDE which provides Drag and Drop [DAD] palettes also known as GUI Builders for above toolkits for programmer's convenience.
Mostly used IDEs are:
It is advised to code manually to develop the GUI rather using GUI builders provided by different IDEs. And for beginners.  


Saturday, 21 October 2017

Launch Swing GUI always in a dedicated Thread



1. Since Swing is not thread safe, it is not at all a good practice to launch a UI Container like JFrame, JDialog etc in main Thread.
2. Doing so leads to incorrect behavior of java GUI.
3. To avoid this, Swing toolkit has predefined API as part of JFC.
4.    a. SwingUtilities.invokeAndWait(Runnable r);
       b. SwingUtilities.invokeLater(Runnable r);

5. Which part of the code must be in UI Thread?
        a. setVisible(true);
        b. show(); [deprecated]
 and c. pack();
     

6. Call to these methods mentioned in 5(a), 5(b), and 5(c) must happen in one of the methods mentioned in point 4(a) and point 4(b). That's enough. :)
         Example :
             
         public static void main(String[] args){
                         
         JFrame frame = new JFrame();
         frame.setSize(100, 200);
         SwingUtilities.invokeAndWait(new Runnable(){
             public void run(){
                     frame.setVisible(true);
                     frame.pack();
             }//run
        });//
       }//main

  7. Difference between invokeAndWait() and invokeLater():
          a. invokeLater() is non blocking and asynchronous, where as invokeAndWait() is blocking and synchronous.
          b. Since invokeLater() is asynchronous, It is more flexible.
                                 
                                   

Friday, 6 October 2017

File Manager/File Explorer with Swing JTree Component

This post is intended to beginners of java swing toolkit programmers.
It is a simple java program which demonstrates the swing based File explorer GUI.





import java.awt.GridLayout;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;

/**
 * @author NagasharathK
 *
 */
public class FileExplorer extends JFrame {

private JTree fileManagerTree = null;

public FileExplorer() {
initComponents();
}

/**
* Initializes components
*/
private void initComponents() {
this.getContentPane().add(new JScrollPane(createFileManagerTree()));
this.setSize(500, 500);
this.setResizable(true);
this.setTitle("File Manager..");
}

/**
* @return JPanel object which contains other comp...
*/
private JPanel createFileManagerTree() {
JPanel panel = new JPanel();
panel.setLayout(new GridLayout());

fileManagerTree = new JTree();
fileManagerTree.setModel(new FilesContentProvider("C:\\"));
panel.add(fileManagerTree);
return panel;
}

class FilesContentProvider implements TreeModel {

private File node;

public FilesContentProvider(String path) {
node = new File(path);

}

@Override
public void addTreeModelListener(TreeModelListener l) {

}

@Override
public Object getChild(Object parent, int index) {
if (parent == null)
return null;
return ((File) parent).listFiles()[index];
}

@Override
public int getChildCount(Object parent) {
if (parent == null)
return 0;
return (((File) parent).listFiles() != null) ? ((File) parent).listFiles().length : 0;
}

@Override
public int getIndexOfChild(Object parent, Object child) {
List<File> list = Arrays.asList(((File) parent).listFiles());
return list.indexOf(child);
}

@Override
public Object getRoot() {
return node;
}

@Override
public boolean isLeaf(Object node) {
return ((File) node).isFile();
}

@Override
public void removeTreeModelListener(TreeModelListener l) {

}

@Override
public void valueForPathChanged(TreePath path, Object newValue) {

}

}

/**
* @param args
* @throws InvocationTargetException
* @throws InterruptedException
* @throws UnsupportedLookAndFeelException
* @throws IllegalAccessException
* @throws InstantiationException
* @throws ClassNotFoundException
*/
public static void main(String[] args) throws InvocationTargetException, InterruptedException,
ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
FileExplorer explorerUI = new FileExplorer();
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
explorerUI.setVisible(true);
}
});
}
}
 

The above program has one inner class [FilesContentProvider] which serves as a model to the JTree.

The UI has 4 Components: JFrame, JScrollPane, JPanel and JTree.

To Do:

  1. Add Context menu to node based upon the file type
  2. Add Cell renderer to give proper names to the Nodes
  3. Option to Expand whole tree or selected node etc..  


Friday, 15 May 2015

JavaFX: arranging components on GridPane

JavaFX provides different layout panes for arranging components on them. for example GridPane, BorderPane etc.
This article describes about arranging components on GridPane. GridPane layout manager allows arranging components/controls using overloaded method. ie add.

                       1. add(controlinstance, colindex, rowindex)

                      EX:  GridPane pane = new GridPane();
                               pane.add(new Separator(), 0, 0);

the above example code puts the separator on 0th row and 0th column of a gridPane.

                     2. add(Node controlinstance,int colIndex,int rowIndex,int colSpan,int rowSpan)   
                          
                     EX: GridPane pane = new GridPane();
                             pane.add(new Separator(),0 , 0, 2, 0);

Following code describes the GridPane with a login screen.


import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.Separator;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Stage;

import com.atmecs.utilities.Validations;


public class Main extends Application {


Button buttonLogin;
Button buttonCancel;
TextField textFieldUsername;
PasswordField PasswordFieldPassword;


@Override
public void start(Stage primaryStage) {

initComponents(primaryStage);

}

private void initComponents(Stage primaryStage) {
        
GridPane gridPane = new GridPane();

gridPane.setHgap(10);
gridPane.setVgap(10);
gridPane.setPadding(new Insets(25, 25, 25, 25));

Scene scene = new Scene(gridPane, 320, 230);
primaryStage.setScene(scene);

Text title = new Text("Login");
title.setFont(Font.font("Tahoma", FontWeight.BOLD, 20));
gridPane.add(title, 0, 0, 2, 1);

Label labelUsername = new Label("Username:");
gridPane.add(labelUsername, 0, 1);
textFieldUsername = new TextField();
gridPane.add(textFieldUsername, 1, 1);

Label labelPassword = new Label("Password:");
gridPane.add(labelPassword, 0, 2);
PasswordFieldPassword = new PasswordField();
gridPane.add(PasswordFieldPassword, 1, 2);

buttonLogin = new Button("Login");


buttonCancel = new Button("Cancel");

gridPane.add(new Separator(), 0, 4, 2, 1);
HBox hbBtn = new HBox(10);
hbBtn.setAlignment(Pos.BOTTOM_RIGHT);
hbBtn.getChildren().add(buttonLogin);
hbBtn.getChildren().add(buttonCancel);

gridPane.add(hbBtn, 1, 5);

primaryStage.show();
setListeners();
}
        public static void main(String[] args) {
launch(args);
}

}





Output:

Friday, 22 July 2011

JColorComboBox: JComboBox as Color Chooser

 
Swing toolkit provides a component called JColorChooser to choose colors. It allows users to select color from multiple color combinations. Some times our application may need simple component with an option to select only basic colors/ less number of color options unlike sepearate dialog with too may color options[JColorChooser]. This JColorComboBox may serve the need.

I wanted my color chooser to behave like JComboBox. The popup shows all 12 colors and their names, among all of them one color can be choosen. see the below image.


I created two classes
         1. JColorComboBox
         2. ColorRenderer
JColorComboBox extends the JComboBox and ColorRenderer extends JLabel and implements ListCellRenderer.


import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.swing.*;
/**
*
* @author sharath
*/
public class JColorComboBox extends JComboBox {

static Hashtable<String, Color> colors;

public JColorComboBox() {
super();
DefaultComboBoxModel model = new DefaultComboBoxModel();
Enumeration colorNames = addColors().keys();
while(colorNames.hasMoreElements()){
String temp = colorNames.nextElement().toString();
model.addElement(temp);
System.out.println("colors"+temp);
}
setModel(model);
setRenderer(new ColorRenderer());
this.setOpaque(true);
this.setSelectedIndex(0);
}
@Override
public void setSelectedItem(Object anObject) {
super.setSelectedItem(anObject);

setBackground((Color)colors.get(anObject));
setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 15));
if(anObject.toString().equals("BLACK") || anObject.toString().equals("DARK_GRAY")){
setForeground(Color.white);
}
}
public Color getSelectedColor(){

return this.getBackground();
} 

private Hashtable addColors(){

colors = new <String, Color>Hashtable();

colors.put("WHITE", Color.WHITE);
colors.put("BLUE", Color.BLUE);
colors.put("GREEN", Color.GREEN);
colors.put("YELLOW", Color.YELLOW);
colors.put("ORANGE", Color.ORANGE);
colors.put("CYAN", Color.CYAN);
colors.put("DARK_GRAY", Color.DARK_GRAY);
colors.put("GRAY", Color.GRAY);
colors.put("RED", Color.RED);
colors.put("PINK",Color.PINK);
colors.put("MAGENTA", Color.MAGENTA);
colors.put("BLACK", Color.BLACK);

return colors;
}
 
class ColorRenderer extends JLabel implements javax.swing.ListCellRenderer {
public ColorRenderer() {
this.setOpaque(true);
}
public Component getListCellRendererComponent(JList list, Object key, int index,
boolean isSelected, boolean cellHasFocus) {

Color color = colors.get(key);;
String name = key.toString();

list.setSelectionBackground(null);
list.setSelectionForeground(null);

if(isSelected){
setBorder(BorderFactory.createEtchedBorder());
} else {
setBorder(null);
}
setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 15));
setBackground(color);
setText(name);
setForeground(Color.black);
if(name.equals("BLACK") || name.equals("DARK_GRAY")){
setForeground(Color.white);
}

return this;
}
}
}

Demo Application:
The below code creates a JFrame by adding JColorComboBox to it.

 

/**
*
* @author sharath
*/
import java.awt.GridLayout;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.*;
public class StartGUIApp {
public static void main(String[] args)throws Exception {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
JFrame.setDefaultLookAndFeelDecorated(true);

JPanel panel = new JPanel();
JLabel label = new JLabel("Select Color");
JColorComboBox box = new JColorComboBox();
panel.add(box);
panel.add(label);
panel.setLayout(null);
label.setBounds(20,20,60,30);
box.setBounds(100,20,140,30);
panel.setSize(250, 100);

JFrame frame = new JFrame();
frame.getContentPane().add(panel);
frame.setSize(panel.getWidth(), panel.getHeight());
setFrameProperties(frame);
}
static private void setFrameProperties(JFrame frame) {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}

Saturday, 9 July 2011

DesignGridLayout: Simple, yet powerful Layoutmanager for arranging swing components

Swing toolkit comes with few standard Layout Managers where none of them serves the need of arranging components in a way that usually developers require. some of them does, but it takes lot of coding time to achieve it. GridBagLayout is the most flexible layout manager available in swing toolkit but their are so many variables that developer has to look after.

DesignGridLayout can be a useful LayoutManager to arrange components in less time with very small snippet of code and can still get proper alignment. Layouting with DesignGridLayout is as easy as coding with various GUI Builder tools available in varoius IDEs.

Simple program which demonstrates DesignGridLayout:

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import net.java.dev.designgridlayout.DesignGridLayout;
import net.java.dev.designgridlayout.Tag;

public class DesignGridLayoutDemo extends JPanel{

  public DesignGridLayoutDemo () {

      DesignGridLayout layout = new DesignGridLayout(this);
      layout.row().grid().add(new JLabel("Username: ")).add(new JTextField("Enter user name "), 2);

      layout.row().grid().add(new JLabel("Password: ")).add(new JTextField("Enter password "), 2);
      layout.emptyRow();layout.emptyRow();
      layout.row().center().fill().add(new JSeparator());
      layout.emptyRow();layout.emptyRow();
      layout.row().bar().add(new JButton(" Login "), Tag.OK).add(new JButton("Cancel"), Tag.CANCEL);
  }


public static void main(String[] args) throws ClassNotFoundException,
                                InstantiationException,
                                IllegalAccessException,
                                UnsupportedLookAndFeelException {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
     SwingUtilities.invokeLater(new Runnable() {

         @Override
    public void run() {
          JFrame frame = new JFrame("Login Form");
          frame.getContentPane().add(new DesignGridLayoutDemo ());
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

          frame.pack();
          frame.setVisible(true);
         }
     });
  }
}
Output:
                                                            
This project has been hosted in java.net site where we can find Tutorial, download links and feature etc.

Popular posts

Atomicity with Java Programming Language

 Atomicity with Java What is Atomicity Atomicity, in computer science, is considered to be a property [ALL-OR-NOTHING], that the state of a ...