advanced programming lab 6
play

Advanced Programming Lab 6 Graphical User Interface (GUI) Swing - PowerPoint PPT Presentation

Advanced Programming Lab 6 Graphical User Interface (GUI) Swing Standard toolkit, included in JDK Standard UI components, lots of them No new functionality introduction for the future Java FX GUI library, not include in JDK


  1. Advanced Programming Lab 6

  2. Graphical User Interface (GUI) ● Swing – Standard toolkit, included in JDK – Standard UI components, lots of them – No new functionality introduction for the future ● Java FX – GUI library, not include in JDK (anymore...) – Rich GUI components, fancy – Modern, new features added with new version

  3. The MainFrame class public class MainFrame extends JFrame { ConfigPanel configPanel; ControlPanel controlPanel; DrawingPanel canvas; public MainFrame() { super("My Drawing Application"); init(); } private void init() { setDefaultCloseOperation(EXIT_ON_CLOSE); //create the components canvas = new DrawingPanel(this); ...TODO //arrange the components in the container (frame) //JFrame uses a BorderLayout by default add(canvas, CENTER); //this is BorderLayout.CENTER ...TODO //invoke the layout manager In the Main class, in the main method: pack(); new MainFrame().setVisible(true); } }

  4. The ConfigPanel class In the MainFrame class, create an instance of this class, and add it in NORTH public class ConfigPanel extends JPanel { final MainFrame frame; JLabel label; // we’re drawing regular polygons JSpinner sidesField; // number of sides JComboBox colorCombo; // the color of the shape public ConfigPanel(MainFrame frame) { this.frame = frame; init(); } private void init() { //create the label and the spinner sidesLabel = new JLabel("Number of sides:"); sidesField = new JSpinner(new SpinnerNumberModel(0, 0, 100, 1)); sidesField.setValue(6); //default number of sides //create the colorCombo, containing the values: Random and Black ...TODO add(sidesLabel); //JPanel uses FlowLayout by default add(sidesField); add(colorCombo); } }

  5. The ControlPanel class In the MainFrame class, create an instance of this class, and add it in SOUTH public class ControlPanel extends JPanel { final MainFrame frame; JButton saveBtn = new JButton("Save"); //create all buttons (Load, Reset, Exit) ...TODO public ControlPanel(MainFrame frame) { this.frame = frame; init(); } private void init() { //change the default layout manager (just for fun) setLayout(new GridLayout(1, 4)); //add all buttons ...TODO //configure listeners for all buttons saveBtn.addActionListener( this::save ); ...TODO } private void save(ActionEvent e) { try { ImageIO.write(frame.canvas.image, "PNG", new File("d:/test.png")); } catch (IOException ex) { System.err.println(ex); } } ...TODO }

  6. The DrawingPanel class In the MainFrame class, create an instance of this class, and add it in SOUTH public class ControlPanel extends JPanel { final MainFrame frame; JButton saveBtn = new JButton("Save"); //create all buttons (Load, Reset, Exit) ...TODO public ControlPanel(MainFrame frame) { this.frame = frame; init(); } private void init() { //add all buttons ...TODO //configure listeners for all buttons saveBtn.addActionListener( this::save ); ...TODO } private void save(ActionEvent e) { try { ImageIO.write(frame.canvas.image, "PNG", new FileOutputStream("d:/test.png")); } catch (IOException ex) { System.err.println(ex); } } ...TODO }

  7. The DrawingPanel class We use direct drawing into an offscreen Image. public class DrawingPanel extends JPanel { final MainFrame frame; final static int W = 800, H = 600; BufferedImage image ; //the offscreen image Graphics2D graphics ; //the "tools" needed to draw in the image public DrawingPanel(MainFrame frame) { this.frame = frame; createOffscreenImage(); init(); } private void createOffscreenImage () { image = new BufferedImage(W, H, BufferedImage.TYPE_INT_ARGB); graphics = image.createGraphics(); graphics.setColor(Color.WHITE); //fill the image with white graphics.fillRect(0, 0, W, H); } //...NEXT SLIDE }

  8. The DrawingPanel class (continued...) private void init() { setPreferredSize (new Dimension(W, H)); //don’t use setSize. Why? setBorder(BorderFactory.createEtchedBorder()); //for fun this.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { drawShape(e.getX(), e.getY()); repaint(); } //Can’t use lambdas, JavaFX does a better job in these cases }); } private void drawShape (int x, int y) { int radius = ... TODO; //generate a random number int sides = ...TODO; //get the value from UI (in ConfigPanel) Color color = ...TODO; //create a transparent random Color. graphics.setColor(color); graphics.fill(new RegularPolygon (x, y, radius, sides)); } @Override public void update(Graphics g) { } //Why did I do that? @Override protected void paintComponent(Graphics g) { g.drawImage(image, 0, 0, this); } }

  9. The RegularPolygon class public class RegularPolygon extends Polygon { public RegularPolygon(int x0, int y0, int radius, int sides) { double alpha = 2 * Math.PI / sides; for (int i = 0; i < sides; i++) { double x = x0 + radius * Math.cos(alpha * i); double y = y0 + radius * Math.sin(alpha * i); this.addPoint((int) x, (int) y); } } }

  10. Create other Shapes public class NodeShape extends Ellipse2D.Double { public NodeShape(double x0, double y0, double radius) { super(x0 - radius / 2, y0 - radius / 2, radius, radius); } } Ellipse2D.Double also implements Shape → Take a look at Shape interface and its implementations: Arc2D, Arc2D.Double, Arc2D.Float, Area, BasicTextUI.BasicCaret, CubicCurve2D, CubicCurve2D.Double, CubicCurve2D.Float, DefaultCaret, Ellipse2D, Ellipse2D.Double, Ellipse2D.Float, GeneralPath, Line2D, Line2D.Double, Line2D.Float, Path2D, Path2D.Double, Path2D.Float, Polygon, QuadCurve2D, QuadCurve2D.Double, QuadCurve2D.Float, Rectangle, Rectangle2D, Rectangle2D.Double, Rectangle2D.Float, RectangularShape, RoundRectangle2D, RoundRectangle2D.Double, RoundRectangle2D.Float → You may create a custom Shape implementation (bonus!)

  11. Direct vs. Retained Drawing ● Direct mode (like in Paint) – We store the drawing using a single image – Individual Shapes are lost – paintComponent simply draws the image ● Retained mode (like in PhotoShop) – We store ALL Shapes in a data structure – List<Shape> shapes ; – paintComponent draws all the shapes, one by one

  12. JavaFX implementation (on your own with a small bonus ) ● JavaFX https://openjfx.io/ ● Get Started https://openjfx.io/openjfx-docs/ ● Scene Builder: https://gluonhq.com/products/scene-builder/

Recommend


More recommend