Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: GUI и Java FX приложения > Где взять пример простейшей программы рисовалки?


Автор: JavaNewb 5.3.2008, 02:14
Я только начинаю изучать Яву. Весьма непривычный язык, надо сказать.
Есть ли где-то собрание лёгких примеров демонстрирующих работу кнопок, обработка их событий и т.д.?

В частности интересует небольшой примерчик программы реализующий рисование курсором мыши. Нет ли где такого?
Там много чего интересного можно почерпнуть - и прорисовку, и обработки событий...

Спасибо!

Автор: Kangaroo 5.3.2008, 02:26
Цитата(JavaNewb @  5.3.2008,  01:14 Найти цитируемый пост)
Есть ли где-то собрание лёгких примеров демонстрирующих работу кнопок, обработка их событий и т.д.?

Вот - http://java.sun.com/docs/books/tutorial/uiswing/, лучшее, что есть по Свингу. С примерами и объяснениями.


Цитата(JavaNewb @  5.3.2008,  01:14 Найти цитируемый пост)
В частности интересует небольшой примерчик программы реализующий рисование курсором мыши. Нет ли где такого?

Вот мой с многочисленными комментариями:
Код

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

/*
 * Class - Java Paint - allows a user to paint on a panel
 */
public class JavaPaint extends JPanel implements ActionListener, ItemListener {        

    //color of brush
    private Color brushColor;
    //background color of paint panel
    private Color backgroundColor;
    //size of brush
    private int brushSize = 6;
    
    JLabel brushSizeLabel;
    JComboBox brushSizeCombo;
    JButton selectColor;
    
    //constructor - create instance of Java Paint    
    public JavaPaint() {    
        //set border layout
        super(new BorderLayout());
        //create GUI
        createGUI();
    }

    //entry point of the application
    public static void main(String[] args) {
        //create main frame with title "Java Paint"
        JFrame frame = new JFrame("Java Paint");                
        
        //add main Panel to frame
        frame.add(new JavaPaint());
        
        //configure frame
        //exit when user clicks close
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //disable resize
        frame.setResizable(false);
        //set preferred size
        frame.setPreferredSize(new Dimension(500, 550));
        frame.pack();       
        //set location of the frame to center
        frame.setLocationRelativeTo(null);
        //show frame
        frame.setVisible(true);
    }

    //creat GUI - components
    private void createGUI() {    
        //create paint panel
        PaintPanel paintPanel = new PaintPanel();
        //get background color of paintPanel
        backgroundColor = paintPanel.getBackground();
        //add paintPanel to the main panel
        this.add(paintPanel, BorderLayout.CENTER);
        
        //create bottom(control) panel
        JPanel bottomPanel = new JPanel();
        //change color of the panel
        bottomPanel.setBackground(Color.LIGHT_GRAY);
        //set border to panel (for alignment)
        bottomPanel.setBorder(BorderFactory.createEmptyBorder(20, 0, 20, 0));
        
        //create label
        brushSizeLabel = new JLabel("Set the brush size: ");
        //add label to bottom panel
        bottomPanel.add(brushSizeLabel);
        
        //create combobox for brush size
        brushSizeCombo = new JComboBox();
        //disable editing
        brushSizeCombo.setEditable(false);
        //loop through 1 to 10
        for (int i=1; i<11; i++) {
            //add item to combobox ("1", "2", "3" and so on... )
            brushSizeCombo.addItem(String.valueOf(i));
        }
        //choose default item for combobox
        brushSizeCombo.setSelectedIndex(4);
        //add item listener (to listen for changes)
        brushSizeCombo.addItemListener(this);
        //add combobox to bottom panel
        bottomPanel.add(brushSizeCombo);
        
        //create empty area between combobox and button
        bottomPanel.add(Box.createRigidArea(new Dimension(50, 0)));
        
        //create button for selecting color
        selectColor = new JButton("Select Paint Color");
        //add action listener
        selectColor.addActionListener(this);
        //add button to bottom panel
        bottomPanel.add(selectColor);
        
        //add bottom panel to main panel
        this.add(bottomPanel, BorderLayout.PAGE_END);
    }
    
    //class - panel for painting
    private class PaintPanel extends JPanel implements MouseMotionListener {
        //image for buffering and saving picture
        Image bufferImage;
        //graphic to draw
        Graphics backgroundGraphics;
        
        //constructor of PainPanel
        public PaintPanel() {
            //set sizes of the panel
            this.setPreferredSize(new Dimension(500, 400));
            this.setSize(new Dimension(500, 400));
            
            //add mouse motion listener to listen for dragging
            this.addMouseMotionListener(this);

        }
        
        //we don't need this method
        //write it 'cause we implement MouseMotionListener
        public void mouseMoved( MouseEvent e ) { }
        
        //run if user dragged mouse
        public void mouseDragged(MouseEvent e) {
         //get location of mouse
         int x = e.getX();
            int y = e.getY();
            //find if user clicked left or right button
            if (SwingUtilities.isLeftMouseButton(e)) {
             //if left - set color to bruseh - paint on panel
             backgroundGraphics.setColor(brushColor);
            }
            else {
             //if right - set color to background - erase from panel
             backgroundGraphics.setColor(backgroundColor);
            }
            
            //paint oval on buffered image
            backgroundGraphics.fillOval(x-brushSize/2,y-brushSize/2,brushSize,brushSize);
            
            //repaint panel
            repaint();
        }
        
        //create buffered image if it doesn't exist
        private void createBufferedImage() {
         Dimension d = getSize();
         //if no image - create it
         if (bufferImage == null) {
             bufferImage = createImage(d.width, d.height);
         }
        }
        
        //update panel by drawing buffered image on it
        public void update( Graphics g ) {
            g.drawImage( bufferImage, 0, 0, this );
        }

        //paint on panel
        public void paint( Graphics g ) {
            //create buffered image if it doesn't exist
            createBufferedImage();            
            //set background graphics to image graphics
            backgroundGraphics = bufferImage.getGraphics();    
            //update panel
            update(g);
        }
        
    }
    
    //user clicked select paint color button
    public void actionPerformed(ActionEvent e) {
        //show color dialog and get new color
        Color newColor = JColorChooser.showDialog(
                                       JavaPaint.this,
                                       "Select Paint Color",
                                       brushColor);
        //check if user selected new color
        if (newColor != null) {
         //set brush color to new
            brushColor = newColor;
        }
    }

    //user changed combobox
    public void itemStateChanged(ItemEvent e) {
        //check if user select item
        if (e.getStateChange() == ItemEvent.SELECTED) {
            //get selected item as string
            String newBrushSize = (String)e.getItem();
            //set brush size
            brushSize = Integer.parseInt(newBrushSize)+1;
        }
        
    }
}


Автор: JavaNewb 5.3.2008, 02:33
Круто! То, что нужно! Спасибо большое!

Туториал свинговский я посмотрел уже. Видел всякие "SwingPaintDemo4Project". Но то, что ты дал - просто супер по сравнению с "SwingPaintDemo4Project" smile

Автор: JavaNewb 5.3.2008, 02:55
А зачем здесь буферизируется изображение? Почему это необходимо делать??

Автор: Kangaroo 5.3.2008, 10:21
Цитата(JavaNewb @  5.3.2008,  01:55 Найти цитируемый пост)
А зачем здесь буферизируется изображение? Почему это необходимо делать?? 

Чтобы сохранять то, что пользователь уже нарисовал. Если бы не было этого буфера, то при перирисовки окна (например, при изменении размера) все изображение пропадало бы.

Автор: JavaNewb 5.3.2008, 21:41
Kangaroo, спасибо за объяснение!
Проголосовал за тебя! (в подписи) smile

Вот ещё что непонятно.. Зачем там существует переменная backgroundGraphics.
Я вижу только то, что там она объявляется, устанавливается цвет на нёё, рисуется овал на этом "графическом контексте" (если можно так выразиться) и ещё делается вот это:
backgroundGraphics = bufferImage.getGraphics();
насколько я понял это присваивание (копирование) bufferImage в backgroundGraphics. Но больше ничего с этим backgroundGraphics и не делается.. А какая же цель её существования там??
Эту переменную ведь никуда не переносят и никак её и не используют, как я понял... Зачем же она нужна?

Автор: Kangaroo 6.3.2008, 01:32
Цитата(JavaNewb @  5.3.2008,  20:41 Найти цитируемый пост)
устанавливается цвет на нёё, рисуется овал на этом "графическом контексте" (если можно так выразиться)

Все правильно.
То что пользователь рисует мы рисуем на bufferImage, а точнее на "графическом контексте" этой картинка - backgroundGraphics.
Так что этой строкой:
backgroundGraphics = bufferImage.getGraphics();
мы просто связываем переменную backgroundGraphics, с "графическом контекстом" картинки, чтобы потом рисовать на ней.

Автор: JavaNewb 6.3.2008, 03:56
Цитата
То что пользователь рисует мы рисуем на bufferImage, а точнее на "графическом контексте" этой картинка - backgroundGraphics.

Вот это как не получается понять smile
Всё, что пользователь рисует мы кидаем на bufferImage.. но причём же тут вообще backgroundGraphics? Не очень понятная технология smile

Получается мы рисуем напрямую на bufferImage и потом ЕЁ же отрисовываем на панель:
Код
public void update( Graphics g ) {
            g.drawImage( bufferImage, 0, 0, this );
        }

а причём же здесь backgroundGraphics, если она в этом процессе не используется? smile

Я уже попробовал убрать и оно не стало работать. Понятно, что оно зачем-то нужно, но вот зачем именно так врубиться и не могу :(

Автор: Kangaroo 6.3.2008, 10:22
Цитата(JavaNewb @  6.3.2008,  02:56 Найти цитируемый пост)
Получается мы рисуем напрямую на bufferImage

Мы не прямо на bufferImage рисуем, а через его graphics - backgroundGraphics
Вот, смотри:
Код

//find if user clicked left or right button
if (SwingUtilities.isLeftMouseButton(e)) {
             //if left - set color to bruseh - paint on panel
             backgroundGraphics.setColor(brushColor);
}
else {
             //if right - set color to background - erase from panel
             backgroundGraphics.setColor(backgroundColor);
}
            
//paint oval on buffered image
backgroundGraphics.fillOval(x-brushSize/2,y-brushSize/2,brushSize,brushSize);

Это у graphics есть методы setColor, fillOval, drawLine, etc. У image их нету.

Автор: JavaNewb 6.3.2008, 21:17
а.. "Вон оно чё!" smile
Т.е. получается, что после кода:
backgroundGraphics = bufferImage.getGraphics();
backgroundGraphics становится как будто ссылкой на bufferImage и рисуя на backgroundGraphics у нас меняется и содержимое bufferImage??
Фигасе финт ушами smile

Автор: JavaNewb 10.3.2008, 03:18
Так я понял? или нет всё-таки??

Автор: Kangaroo 10.3.2008, 12:17
Цитата(JavaNewb @  6.3.2008,  20:17 Найти цитируемый пост)
backgroundGraphics становится как будто ссылкой на bufferImage и рисуя на backgroundGraphics у нас меняется и содержимое bufferImage??

backgroundGraphics это не "как будто ссылка", а объект класса, у которого есть функциональность для рисования на bufferImage.
Не знаю как красиво сказать  smile 

Автор: DelphiFun 12.3.2008, 07:17
[удалено]

Автор: JavaNewb 5.6.2008, 12:21
Kangaroo, если позволишь - ещё вопрос! smile

Если в вышеидущем коде необходимо нарисовать что-то до того как пользователь начнёт рисовать где можно такой код прописать?

Я попытался сделать это вот здесь:
Код

//class - panel for painting
private class PaintPanel extends JPanel implements MouseMotionListener {
    //image for buffering and saving picture
    Image bufferImage;
    //graphic to draw
    Graphics backgroundGraphics;
    
    //constructor of PainPanel
    public PaintPanel() {
        this.setPreferredSize(new Dimension(500, 400));
        this.setSize(new Dimension(500, 400));
        this.addMouseMotionListener(this);

// -----------------------------------------------------    
        repaint();
        backgroundGraphics.fillOval( 0, 0, 100, 100 );
// -----------------------------------------------------

    }

но получил вот такую ошибку:
Код
Exception in thread "main" java.lang.NullPointerException
        at JavaPaint$PaintPanel.<init>(JavaPaint.java:102)
        at JavaPaint.createGUI(JavaPaint.java:61)
        at JavaPaint.<init>(JavaPaint.java:19)
        at JavaPaint.main(JavaPaint.java:26)


Он о чём говорит? То, что "backgroundGraphics" не инициализировано ещё?
Но разве вызываемый перед этим метод paint() не инициализирует "backgroundGraphics"?

Автор: JavaNewb 6.6.2008, 08:14
Кстати, а как в данном случае вообще из родительского класса обратиться к переменной backgroundGraphics? т.е. например из функции public static void main(String[] args)?

Автор: JavaNewb 6.6.2008, 17:39
Попытался сделать переменную backgroundGraphics глобальной, выдаёт вот это:
Код
JavaPaint.java:55: non-static variable backgroundGraphics cannot be referenced from a static context
                                backgroundGraphics.fillOval(0,0,100,100);
                                ^
1 error

Что означает эта ошибка? Как обойти её можно?

Насколько я понимаю - я хочу сделать переменную backgroundGraphics нестатической, а оно мне говорит, что делать её таковой нельзя? smile

Автор: JavaNewb 7.6.2008, 11:48
Справился! отбой! smile
Добавлением новых методов, которые возвращали эти "недосягаемые" переменные.

Автор: lift 4.6.2009, 12:19
Посоветуйте пожалуйста как решить следующую проблему: необходимо создать что-то  типа простенького графического редактора для просмотра и изменения рисунков (jpg,gif..), фильтры, всякие, наложения и, конечно, рисование. Вот как раз с рисованием и возникли проблемы(никогда раньше не программировал графику, да и в яве я новичок, раньше в основном с дельфи работал). За основу для рисования взял код выложенный Kangaroo на предыдущей странице (спасибо ему большое кстати). Но там рисование производилось на пустом рисунке:
Код

Image bufferImage = createImage(d.width, d.height);

когда я пытаюсь сделать что-то вроде этого 
Код

Image bufferImage = Toolkit.getDefaultToolkit().getImage(ImageURL);

то при перерисовке ява ругается на метод 
Код

bufferImage.getGraphics()

пишет: Exception in thread "AWT-EventQueue-0" java.lang.UnsupportedOperationException: getGraphics() not valid for images created with createImage(producer).
Никак не могу это обойти, посовейте что-нибудь, пожалуйста, или хотя бы где искать.


Автор: math64 4.6.2009, 12:55
используй java.awt.image.BuferedImage для рисования и пакет javax.imageio.* для загрузки и сохранения

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)