Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > сначало нарисовать 10 картинок..


Автор: polosatij 15.11.2004, 15:40
сначало нарисовать 10 картинок.. потом показать их пользователю.. как осуществить?

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

как мне сначало нарисовать картинки, а потом показать их?
я не могу себе позволить работать пиксельно с большими Array-ами, так как всё будет тормозить НА НЕТ smile

мне нужна здесь если не молнееносная реакция, то хотябы приблежение к ней..

может кто что хорошее предложит smile

Автор: Domestic Cat 15.11.2004, 16:28
я не понял, как нарисовать и что нарисовать? если задача в том, чтобы сделать из 10 разных картинок 1 рисунок, то нужно просто создать BufferedImage, взять у него графику (getGraphics()) и нарисовать туда эти рисунки.

Автор: igon 16.11.2004, 05:01
Если нужно, чтобы 10 отдельных картинок только "выглядели", как одна, то можно использовать JLayeredPane, разместив каждую картинку в отдельном слое, самый верхний слой предварительно "залить" каким-нибудь нейтральным фоном. По окончании загрузки всех картинок "утопить" (moveToBack) верхний слой и перерисовать JLayeredPane

Автор: Domestic Cat 16.11.2004, 07:11
Окончание загрузки не означает что все картинки будут прорисовываться одновременно и не будет мерцания. В момент "утопления" верхнего слоя мы получим то же самое, что было бы при прорисовке картинок на одной панели.
Мерцание возникает из-за того, что прорисовать 10 рисунков медленнее, чем один большой. Потому лучше рисовать в один рисунок, тем более что если его составляющие со временем не меняются, то нужно будет делать эту прорисовку 1 раз. Это называется двойным буффированием.

Автор: polosatij 16.11.2004, 09:06
Цитата(Domestic @ 15.11.2004, 16:28)
я не понял, как нарисовать и что нарисовать? если задача в том, чтобы сделать из 10 разных картинок 1 рисунок, то нужно просто создать BufferedImage, взять у него графику (getGraphics()) и нарисовать туда эти рисунки.



что-то не получается у меня.. где я ошибаюсь smile

Код


//сначала устанавливаем размер и тип BuffederImage
BufferedImage bi= new BufferedImage(300, 400, BufferedImage.TYPE_INT_RGB);

//затем врисовываем туда картинки:
bi.getGraphics().drawImage(im1, 0, 0, canvas); // Canvas canvas..
bi.getGraphics().drawImage(im2, 0, 0, canvas);
...

//теперь естественно содержимое нужно показать в canvas-е..

Canvas canvas= new Canvas() {
 public void paint(Graphics g) {
   
    // теперь нужен Image из BufferedImage сделать..
     // .. вот тут вот я и затрудняюсь.. я выбрал следующее:
ImageFilter filter = new CropImageFilter(0, 0, 300, 400);
Image newImage= createImage(new FilteredImageSource(bi.getSource(), filter);

    // теперь врисовываю содержимое в canvas:
g.drawImage(newImage, 0, 0, canvas);

// и на выходе получается ерунда ->
// 1. у меня рисунок был в некоторых местах транспарентным --> стал черным
// 2. смещение какое-то вправо на 50 пикселей
// 3. после перерисовки моя картинка сьезжает вправо на 30-40 пикселей..
// 4. и т.п... и т.п...
 }
};



где я ошибся?
Добавлено @ 09:08
Цитата(Domestic @ 16.11.2004, 07:11)
то нужно будет делать эту прорисовку 1 раз. Это называется двойным буффированием.


нет.. у меня не получиться этого.. картинка каждый раз - разная.. возможных вариантов 100^100, если не больше..

Автор: Domestic Cat 16.11.2004, 10:00
Код

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

public class tst extends JFrame
{  

   public tst()
   {
       Image im1 = new ImageIcon("av-4437.jpg").getImage();
       int width = im1.getWidth(null);
       int height = im1.getHeight(null);
       setSize(300, 300);
       BufferedImage bi= new BufferedImage(300, 400, BufferedImage.TYPE_INT_RGB);
       Graphics g = bi.getGraphics();
       g.drawImage(im1, 0, 0, null);
       g.drawImage(im1, 0, height, null);
       g.drawImage(im1, width, 0, null);
       g.drawImage(im1, width, height, null);
       g.dispose();
       JPanel panel = new MyPanel(bi);
       getContentPane().add(panel, BorderLayout.CENTER);
       setVisible(true);
       setDefaultCloseOperation(EXIT_ON_CLOSE);
   }
   
   public static void main(String args[])
   {
       new tst();
   }
   
   class MyPanel extends JPanel
   {
       private Image im;
       MyPanel(Image image)
       {
           im = image;
           setPreferredSize(new Dimension(300, 300));
       }
       
       public void paintComponent(Graphics g)
       {
           g.drawImage(im, 0, 0, null);
       }
   }
}


Насчет черного фона - нужно канве сделать setOpaque.


Цитата(polosatij @ 16.11.2004, 00:06)
нет.. у меня не получиться этого.. картинка каждый раз - разная.. возможных вариантов 100^100, если не больше..


ну так тем более

Автор: igon 18.11.2004, 09:10
Никак не удается воспроизвести мерцание при отображения 10 отдельных фрагментов общей картинки (PIII-800, ОЗУ 512, Win2000, JDeveloper10) при использовании JLayeredPane. smile

Код

import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.lang.ClassCastException;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;

// В каталоге Images должны быть картинки с именами 1.jpg, 2.jpg,...10.jpg,  
// Click на картинке позволяет перемещать ее по экрану
// Повторный Click отключает перемещение и добавляет очередную картинку
public class JLayeredPaneTest extends JPanel
                             implements MouseMotionListener,
                                        MouseListener {

 JLayeredPane layeredPane;
 JLabel       activLabel;
 boolean      moveEnable = false;
 String       moveOn     = "Режим перемещения включен. Кликнете на картинке для отключения";
 String       moveOff    = "Режим перемещения выключен. Кликнете на картинке для включения";
 //This is the origin of the first image added.
 Point origin = new Point(10, 20);

 //This is the offset for computing the origin for the next image
 int offset = 15;
 // Image counter
 int i = 1;

 public JLayeredPaneTest()    
   {
     setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
     layeredPane = new JLayeredPane();
     layeredPane.setPreferredSize(new Dimension(800, 500));
     layeredPane.setBorder(BorderFactory.createTitledBorder(moveOff));
     layeredPane.addMouseListener(this);

     //Add several overlapping images to the layered pane
     //using absolute positioning/sizing.
     for ( i = 1; i <= 4; i++)
       {
         JLabel label = new JLabel(createImageIcon("images/"+i+".jpg"));
         label.setBounds(origin.x, origin.y, 500, 500);
         layeredPane.add(label, new Integer(i));
         origin.x += offset;
         origin.y += offset;
       }
     add(layeredPane);
   }

   /** Returns an ImageIcon, or null if the path was invalid. */
 protected static ImageIcon createImageIcon(String path)
   {
     java.net.URL imgURL = JLayeredPaneTest.class.getResource(path);
     if (imgURL != null)
       {
         return new ImageIcon(imgURL);
       }
     else
       {
         System.err.println("Couldn't find file: " + path);
         return null;
       }
   }

 public void mouseMoved(MouseEvent e)
   {
     activLabel.setLocation(e.getX(), e.getY());
   }
 public void mouseDragged(MouseEvent e) {}

 public void mouseClicked(MouseEvent e)
   {
     if (moveEnable)
       {
         layeredPane.setBorder(BorderFactory.createTitledBorder(moveOff));
         moveEnable = false;    
         layeredPane.removeMouseMotionListener(this);

         if (i<=10)
           {
             JLabel label = new JLabel(createImageIcon("images/"+i+".jpg"));
             label.setBounds(origin.x, origin.y, 500, 500);
             layeredPane.add(label, new Integer(i));
             origin.x += offset;
             origin.y += offset;
             i++;
           }
       }
     else
       {
         layeredPane.setBorder(BorderFactory.createTitledBorder(moveOn));
         moveEnable = true;    
         layeredPane.addMouseMotionListener(this);
         try
           {
             activLabel =(JLabel)layeredPane.getComponentAt(e.getX(), e.getY());      
           }
           catch (ClassCastException cce)
             {
               layeredPane.setBorder(BorderFactory.createTitledBorder(moveOff));
               moveEnable = false;    
               layeredPane.removeMouseMotionListener(this);
             }
       }
   }
   
 public void mouseReleased(MouseEvent e) {}
 public void mousePressed(MouseEvent e)  {}
 public void mouseExited(MouseEvent e) {}
 public void mouseEntered(MouseEvent e){}

   /**
    * Create the GUI and show it.  For thread safety,
    * this method should be invoked from the
    * event-dispatching thread.
    */
 private static void createAndShowGUI()
   {
     JFrame.setDefaultLookAndFeelDecorated(true);

       //Create and set up the window.
     JFrame frame = new JFrame();
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

       //Create and set up the content pane.
     JComponent newContentPane = new JLayeredPaneTest();
     newContentPane.setOpaque(true); //content panes must be opaque
     frame.setContentPane(newContentPane);

       //Display the window.
     frame.pack();
     frame.setVisible(true);
   }

 public static void main(String[] args)
   {
       //Schedule a job for the event-dispatching thread:
       //creating and showing this application's GUI.
     javax.swing.SwingUtilities.invokeLater(new Runnable()
                                              {
                                                public void run()
                                                  {
                                                    createAndShowGUI();
                                                  }
                                              }
                                            );
   }
}

Автор: Domestic Cat 18.11.2004, 09:14
И не получится без дабл баффера, хоть тут в лепешку расшибись smile

Автор: igon 18.11.2004, 18:28
Цитата

не удается воспроизвести мерцание

Цитата

И не получится без дабл баффера

=> для мерцания нужен дабл баффер

=> счастье - это когда тебя понимают smile


Автор: Domestic Cat 18.11.2004, 19:13
Извиняюсь - действительно не разобрался smile но у тебя картинка прорисовывается 1 раз, и здесь то проблем нет, хоть ты ее на 100 кусков разрежь. В обеих примерах все ок.

Проблемкa будет если тебe нужнo постоянно меняtь рисунок или его части (непрерывно). Поскольку здесь речь об игре, то я предполагаю что-то вроde этогo. Тогдa прорисовыват' придется нe 1 раз, а Н раз в секунду, ну i тогда мерцание будет

Автор: igon 18.11.2004, 19:57
Мдя, похоже, я опять не совсем понял исходную проблему - подразумевалась-то, оказывается, анимация. В этом случае ты прав: о такой проблеме я слыхал и решается она как раз двойной буферизацией (сам, увы, не сталкивался). Хотя, таскание мышой одного (величиной с полэкрана) фрагмента при наличии других - чем не анимация? А мерцание так таки и не появилось, несмотря на усердие в таскании (уж и не знаю, smile или smile )

Автор: Domestic Cat 18.11.2004, 20:07
Ну вроде как polosatij об игрe говорил. А насчет таскания мышой - там fps поменьше smile к тому же таскаешь ("анимируешь") ты ведь 1 рисунок, а для него двойного буфера и не надо.

Автор: polosatij 21.11.2004, 00:52
млин.. Domestic Cat, мучаюсь всё ещё с Траблой..
очень долго не мог понять где ошибка.. и теперь вижу, что перерисовка BufferedImage мне ничего не даёт.. почему-то содержание остаётся прежним.. странно.. мне нужно как-нибудь очищать содержимое BufferedImage smile , если я хочу запихнуть в него другой материал?

странно.. в paint-е всё получается замечательно (можно проверить, поменяв активное окно), а вот те же самые строчки в анонимном классе (при нажатии мыши) не работают.. хм.. smile

Автор: Domestic Cat 21.11.2004, 01:46
А можно код твой посмотреть? А то так непонятно.

Автор: polosatij 22.11.2004, 01:05
Код

....

 Canvas canvas = new Canvas(){
   public void paint(Graphics g){

   graphicsBI= bi.getGraphics(); // BufferedImage bi
   graphicsCanvas=g;
   getFarbe= ChessBoard.altFarbe;

   //esli nikakaja figura ne aktivna:
     if (Figuren.activeFigure.equals("")){
       graphicsBI.drawImage(im, 0, 0, canvas); //im - zadnij fon
     }else{
       //esli figura aktivna:
       imageFilterMethode(boardAltX, boardAltY);  //<- metoda mertva. boardAltX, boardAltY - prostye koordinaty polja
     }

   figuren.risujFigury(graphicsBI, arrayImage, canvas); // Image []arrayImage
   graphicsBI.dispose();

   graphicsCanvas.drawImage(bi, 28, 3, canvas);
 }

   public boolean imageUpdate(Image img, int flags, int x, int y, int width, int height) {
     if ((flags & ImageObserver.ALLBITS) != 0) {
       synchronized(monitor) {
         monitor.notify();
       }
       return false;
     }
     return true;
   }

   public void update(Graphics g){
     paint(graphicsBI);
   }

   public void repaint(){}
 };


 ....
 
     canvas.addMouseListener(new MouseAdapter(){
     public void mousePressed(MouseEvent e){
       ....
               //esli figury mogut hodit':
               if (figuren.erlaubt(feld, xCell, yCell)){
               bi.getGraphics().drawImage(im, 0, 0, canvas); //im - zadnij fon

               figuren.risujFigury(bi.getGraphics(), arrayImage, canvas);

               bi.getGraphics().dispose();
               
               //ne risuet: (v paint-e vse zamechatel'no pri pervom vyzove i pri smene aktivnogo okna)
               //(!!!) pochemu?
               graphicsCanvas.drawImage(bi, 28, 3, canvas);
               }else{
                       ChessBoard.altFarbe = getFarbe;

                       // metoda mertva: (!!!) pochemu?
                       imageFilterMethode(koordinateX, koordinateY);


                       // (!!!) pochemu?
                       figuren.risujFigury(bi.getGraphics(), arrayImage, canvas);

                       bi.getGraphics().dispose();
                       //ne risuet: (v paint-e vse zamechatel'no pri pervom vyzove i pri smene aktivnogo okna)
                       graphicsCanvas.drawImage(bi, 28, 3, canvas);
               }
               
               ....
   
   // posle vnesenija korrektur s BufferedImage <- metoda mertva:
   private void imageFilterMethode(int x, int y) {

   //vyrezaem prjamougol'nik:
   ImageFilter filter = new CropImageFilter(x-50, y-24, 80, 70); //x, y - to mesto, gde kliknuli:
   Image myNewImage= createImage(new FilteredImageSource(im.getSource(), filter));

   filter = new RGBImageFilter(){
     public int filterRGB(int x, int y, int argb){

       if (argb == getFarbe){
         return 0xfff80c17; //nahodim nuzhnym nam zvet i prevrashaem ego v krasnyj:
       }
       return argb;
     }
   };

   Image izmenenieZveta = createImage(new FilteredImageSource(myNewImage.getSource(), filter));
   
   //sm. nizhe: (smysl - narisuj, potom kokazhi (inache ne uspeesh, libo morgnet dlja pol'zovatelja:))
   threadMonitor(izmenenieZveta, canvas);

   graphicsBI.drawImage(im, 0, 0, canvas);
   graphicsBI.drawImage(izmenenieZveta, x-50, y-24, canvas);

   bi.getGraphics().dispose();
   
   //nichego ne proishodit, (!!!) pochemu?
   graphicsCanvas.drawImage(bi, 28, 3, canvas);
 }
 
 ....

   private void threadMonitor(Image im, Canvas canvas) {
   prepareImage(im, canvas);
   synchronized (monitor) {
     try {
       monitor.wait();
     }
     catch (InterruptedException ex) {}
   }
 }



млин.. не знаю.. может BufferedImage надо затерать прежде? может другой использовать? может еще что smile не знаю даже.. smile

-------------------

посмотрел вчера, оказывается в Canvas вообще ничего нарисовать нельзя!!!
может быть можно, но оно не отображается smile

Автор: Domestic Cat 22.11.2004, 18:26
Рисовать в канвe можно, тy просто делаешь неправильно. Воt пример :

Код


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


public class B extends JFrame
{  
   B()
   {
       setSize(400, 400);
       MyCanvas myCanvas = new MyCanvas();
       myCanvas.addMouseListener(myCanvas);
       getContentPane().add(myCanvas, BorderLayout.CENTER);
       setDefaultCloseOperation(EXIT_ON_CLOSE);
       setVisible(true);
   }
   public static void main(String[] args)    
   {
       new B();
   }

}

class MyCanvas extends Canvas implements MouseListener
{
   BufferedImage bi = new BufferedImage(400, 400, BufferedImage.TYPE_INT_RGB);
   Image im1 = new ImageIcon("av-4437.jpg").getImage();
   Image im2 = new ImageIcon("av-3725.gif").getImage();
   MyCanvas()
   {
       Graphics to = bi.getGraphics();
       to.setColor(Color.WHITE);
       to.fillRect(0, 0, 400, 400);
       to.drawImage(im1, 0, 0, im1.getWidth(null), im1.getHeight(null), null);
       to.drawImage(im2, 200, 200, im2.getWidth(null), im2.getHeight(null), null);
       to.dispose();
   }
   public void paint(Graphics g)
   {
       
       g.drawImage(bi, 0, 0, null);
   }
   
   public void mouseClicked(MouseEvent m)
   {
       Graphics to = bi.getGraphics();
       to.setColor(Color.WHITE);
       to.fillRect(0, 0, 400, 400);
       to.drawImage(im1, 200, 200, im1.getWidth(null), im1.getHeight(null), null);
       to.drawImage(im2, 0, 0,im2.getWidth(null), im2.getHeight(null), null);
       to.dispose();
       repaint(); // <------
   }
   
   public void mousePressed(MouseEvent m) {}
   public void mouseReleased(MouseEvent m) {}
   public void mouseExited(MouseEvent m) {}
   public void mouseEntered(MouseEvent m) {}
}


Автор: polosatij 22.11.2004, 19:19
Domestic Cat

почему-то очень многие дают мне пример именно так:
Цитата(Domestic @ 22.11.2004, 18:26)
implements MouseListener


а почему не анонимным классом? это дело вкуса smile
я, например, не люблю когда лишние строки валяются.. (= строки интерфейса)

за пример, паси smile
сегодня попробую чуть по другому smile


Автор: Domestic Cat 22.11.2004, 19:37
можно и анонимным классом, но так увеличивается размер программы (за счет создания отдельного MyCanvas$1.class)

Автор: Zandr 23.11.2004, 12:26
И дело вкуса тоже.
Когда у тебя фрейм с одной кнопкой, можно
Код

class MyApp extends JFrame implements ActionListener

А если у тя куча кнопок, то извиняй smile

Автор: polosatij 23.11.2004, 13:35
Domestic Cat, я посмотрел вчера твой вариант.. и свои.. привожу здесь переделку твоего варианта, под мой: (у меня пара тысяч строк в проекте, мне так просто не переделать это всё на твой лад, поэтому хочу разобраться, где и что я не правильно делаю):

Код

package domestic;

import java.io.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;


public class B extends JFrame implements MouseListener
{
 BufferedImage bi = new BufferedImage(400, 400, BufferedImage.TYPE_INT_RGB);
 Image im1;
 Image im2;
 
 Canvas canvas = new Canvas() {
   public void paint(Graphics g) {
      g.drawImage(bi, 0, 0, null);
   }
 };

 B() {
   setSize(400, 400);
   canvas.addMouseListener(this);
   getContentPane().add(canvas, BorderLayout.CENTER);
   setDefaultCloseOperation(EXIT_ON_CLOSE);
   im1 = new ImageIcon("1.jpg").getImage();
   im2 = new ImageIcon("2.gif").getImage();
   
   Graphics to = bi.getGraphics();
   to.setColor(Color.WHITE);
   to.fillRect(0, 0, 400, 400);
   to.drawImage(im1, 0, 0, null);
   to.drawImage(im2, 200, 200, null);
   to.dispose();
   setVisible(true);
 }

 public static void main(String[] args) {
   new B();
 }

 public void mouseClicked(MouseEvent m) {
 }

 public void mousePressed(MouseEvent m) {
   System.out.println("!");
   Graphics to = bi.getGraphics();
   to.setColor(Color.WHITE);
   to.fillRect(0, 0, 400, 400);
   to.drawImage(im1, m.getX(), m.getY(), null);
   to.drawImage(im2, m.getX() + 10, m.getY() + 10, null);
   to.dispose();
   repaint(); // <------

 }

 public void mouseReleased(MouseEvent m) {}

 public void mouseExited(MouseEvent m) {}

 public void mouseEntered(MouseEvent m) {}
}



почему картинка перерисовывается только после смены активных окон smile
заранее паси smile
Добавлено @ 13:37
Цитата(Domestic @ 22.11.2004, 18:26)
тy просто делаешь неправильно.


до BufferedImage у меня всё работало замечательно (не устраивало лишь мигание и "частота процессора")

Автор: Domestic Cat 23.11.2004, 16:18
repaint() должен перерисовывать канву, а не фрейм, как у тебя:

Цитата
canvas.repaint(); 

Автор: polosatij 23.11.2004, 18:31
У-У-У-У-У-У-У-У-У-У-У-У-У-У-У-У-У-У-Уря-я-я-я-я-я-я.. Заработало! (с) Простоквашино smile

точно.. а я думал.. smile

нужно только еще один кусок подогнать.. вечером принесу..
Domestic Cat кидай домашний адрес, придётся тебе из германии пива прислать smile, детю (детям игрушек), жене цветы =)))

и всё-таки коты понимают друг друга (с) полосатый

Автор: Domestic Cat 23.11.2004, 18:45
Цитата
Domestic Cat кидай домашний адрес, придётся тебе из германии пива прислать , детю (детям игрушек), жене цветы =)))


smile дороговатo выйдет, и вообщe котов спаивать smile гринпис осудит

Цитата
и всё-таки коты понимают друг друга (с) полосатый


АААА так ты тоже Кот??? Растет силa кошачья на форумe smile smile


Автор: AntonSaburov 23.11.2004, 18:51
Пора сынишку на форум выводить, он у меня в год Собаки родился, а то засилье какое-то. Я тут уже видел участника WildCat. Кошмар smile

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