claudiop Posted June 21, 2013 at 08:13 PM Report #514372 Posted June 21, 2013 at 08:13 PM Boas. Eu tenho um programa que estou a fazer, que necessito que fassa render de objectos graficos dentro de uma area "scrollable". O problema é que ainda só coloquei uma imagem simples e já vejo problemas a aparecer, o scroll faz isto: PS: A img é esta: http://www.rarst.net/images/android-tablet-wallpaper-size/android_wallpaper_template_1920x1408.png Como é que posso corrigir isto? Aqui está o codigo que está a fazer o render dentro de um JPanel: import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.JOptionPane; import javax.swing.JPanel; public class Render extends JPanel{ Render(){ super(); } @Override public void paint(Graphics g){ Graphics2D graphObj=(Graphics2D) g; BufferedImage environment = null; try { environment = ImageIO.read(new File("/caminho/para/a/img")); } catch (IOException e) { JOptionPane.showMessageDialog(null, "Não foi possivel carregar a imagem!"); } Dimension environmentSize = getImageSize(environment); super.setPreferredSize(environmentSize); graphObj.drawImage(environment, 0, 0, null); } private Dimension getImageSize(BufferedImage img){ Dimension imgSize = new Dimension(img.getWidth(),img.getHeight()); return imgSize; } } E já agora, se alguem quiser contribuir com ajuda adicional, aceitava um exemplo de como implementar a habilidade de pan e zoom, mesmo que abstractamente. Cumprimentos
Ernest Posted June 22, 2013 at 08:30 AM Report #514411 Posted June 22, 2013 at 08:30 AM Bom dia, Versão simplificada ao extremo : import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JScrollPane; public class ScrollPaneDemo extends JFrame { public ScrollPaneDemo() { super("JScrollPane Imagem"); ImageIcon imagenIcon = new ImageIcon("android_wallpaper_template_1920x1408.png"); JScrollPane jsp = new JScrollPane(new JLabel(imagenIcon)); getContentPane().add(jsp); setSize(1500, 700); setVisible(true); } public static void main(String[] args) { new ScrollPaneDemo(); } } Também tem um bocado mais elaborado mas é para depois ... 1 Report
claudiop Posted June 22, 2013 at 01:23 PM Author Report #514444 Posted June 22, 2013 at 01:23 PM Bom dia, Versão simplificada ao extremo : import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JScrollPane; public class ScrollPaneDemo extends JFrame { public ScrollPaneDemo() { super("JScrollPane Imagem"); ImageIcon imagenIcon = new ImageIcon("android_wallpaper_template_1920x1408.png"); JScrollPane jsp = new JScrollPane(new JLabel(imagenIcon)); getContentPane().add(jsp); setSize(1500, 700); setVisible(true); } public static void main(String[] args) { new ScrollPaneDemo(); } } Também tem um bocado mais elaborado mas é para depois ... Muito obrigado pela sua ajuda. De facto o seu codigo funciona bastante fluido e não cria erros graficos no scroll. O quê é que os estaria a causar, a bufferedImage? Existe alguma desvantagem em utilizar o ImageIcon com uma imagem de elevado tamanho e dimensões? Já exprimentei a imagem a ser utilizada(que tem mais de 15000 pixeis de largura por 4000) e funcionou perfeitamente, mas estranhamente o processo do programa não consumia quase memoria nenhuma. Posso aplicar em ImageIcon's as transformações que são aplicaveis nas BufferedImage's para implementar pan e zoom?(resizes on-the-go) Cumprimentos
Ernest Posted June 22, 2013 at 11:51 PM Report #514531 Posted June 22, 2013 at 11:51 PM Bom dia, A partir de um BufferedImage também se pode fabricar um ImageIcon. O problema é que SWING é baseado no AWT, foi por isso que ECLIPSE foi baseado pela IBM no SWT/JFace que já é melhore mas tem o problema da portabilidade 100%. JavaFX também é muito potente. A diferença fundamentalmente entre o seu código e o meu é que eu não utilizo por enquanto : paint(Graphics g) , paintComponent(Graphics g) , drawImage(..) Uma coisa deste gênero : @Override protected void paintComponent(Graphics g) { super.paintComponent(g); g.drawImage(image, 0, 0, null); } O problema com estes métodos (call Back) paint(Graphiocs g) é que não são previsíveis por serem assíncronos. Nunca se sabe quando serão chamados ... Aqui esta uma versão mais completa : import java.awt.Dimension; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; public class ImageApp extends JPanel { private static final long serialVersionUID = 1L; public ImageApp(JFrame frameParent) { ImageIcon imageIcon = createImageIcon("android_wallpaper_template_1920x1408.png"); JLabel labelImg = new JLabel(imageIcon); labelImg.setHorizontalAlignment(JLabel.CENTER); JScrollPane jsp = new JScrollPane(labelImg); frameParent.getContentPane().add(jsp); } protected ImageIcon createImageIcon(String image) { BufferedImage bufImg = null; try { bufImg = ImageIO.read(new File(image)); Dimension environmentSize = getImageSize(bufImg); super.setPreferredSize(environmentSize); } catch (IOException e) { e.printStackTrace(); } if (bufImg != null) { return new ImageIcon(bufImg); } else { JOptionPane.showMessageDialog(null, "Não encontra a imagem : " + image); return null; } } private Dimension getImageSize(BufferedImage img){ Dimension imgSize = new Dimension(img.getWidth(),img.getHeight()); return imgSize; } private static void createAndShowGUI() { JFrame frameParent = new JFrame("Image App"); frameParent.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); new ImageApp(frameParent); frameParent.setBounds(10, 10, 1000, 800); frameParent.setVisible(true); } public static void main(String[] args) { javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } }); } } No Eclipse pode fazer no teclado Ctrl + i para Indentation do código. Repare que eu envio a frameParent no constructor do JPanel o que lhe permite utilizar o JPanel ImageApp em qualquer JFrame. Repare também que o código no método main(String[] args) faz parte das boas práticas SWING descritas no Web Site da ORACLE / SUN . Conclusão Utilize o Eclipse Kepler (4.3) sobre Java Platform (JDK 1.7_25) com o Google Plugin for Eclipse e o WindowBuilder Pro. Desenvolver interfaces gráficas Java em 5 minutos para : Swing, SWT, RCP, XWT e GWT com WindowBuilder Pro WYSIWYG, drag-and-drop interface. A moda é d'utilizar JavaFX que vem integrado no JDK : What Is JavaFX ? http://docs.oracle.com/javafx/2/overview/jfxpub-overview.htm Mais tarde mostro como fazer o resto , pan, zoom e muito mais com JavaFX e SWING é muito fácil ... Cordialmente Ernest Duarte
claudiop Posted June 24, 2013 at 10:13 PM Author Report #514846 Posted June 24, 2013 at 10:13 PM Bom dia, A partir de um BufferedImage também se pode fabricar um ImageIcon. O problema é que SWING é baseado no AWT, foi por isso que ECLIPSE foi baseado pela IBM no SWT/JFace que já é melhore mas tem o problema da portabilidade 100%. JavaFX também é muito potente. A diferença fundamentalmente entre o seu código e o meu é que eu não utilizo por enquanto : paint(Graphics g) , paintComponent(Graphics g) , drawImage(..) Uma coisa deste gênero : @Override protected void paintComponent(Graphics g) { super.paintComponent(g); g.drawImage(image, 0, 0, null); } O problema com estes métodos (call Back) paint(Graphiocs g) é que não são previsíveis por serem assíncronos. Nunca se sabe quando serão chamados ... Aqui esta uma versão mais completa : import java.awt.Dimension; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; public class ImageApp extends JPanel { private static final long serialVersionUID = 1L; public ImageApp(JFrame frameParent) { ImageIcon imageIcon = createImageIcon("android_wallpaper_template_1920x1408.png"); JLabel labelImg = new JLabel(imageIcon); labelImg.setHorizontalAlignment(JLabel.CENTER); JScrollPane jsp = new JScrollPane(labelImg); frameParent.getContentPane().add(jsp); } protected ImageIcon createImageIcon(String image) { BufferedImage bufImg = null; try { bufImg = ImageIO.read(new File(image)); Dimension environmentSize = getImageSize(bufImg); super.setPreferredSize(environmentSize); } catch (IOException e) { e.printStackTrace(); } if (bufImg != null) { return new ImageIcon(bufImg); } else { JOptionPane.showMessageDialog(null, "Não encontra a imagem : " + image); return null; } } private Dimension getImageSize(BufferedImage img){ Dimension imgSize = new Dimension(img.getWidth(),img.getHeight()); return imgSize; } private static void createAndShowGUI() { JFrame frameParent = new JFrame("Image App"); frameParent.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); new ImageApp(frameParent); frameParent.setBounds(10, 10, 1000, 800); frameParent.setVisible(true); } public static void main(String[] args) { javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } }); } } No Eclipse pode fazer no teclado Ctrl + i para Indentation do código. Repare que eu envio a frameParent no constructor do JPanel o que lhe permite utilizar o JPanel ImageApp em qualquer JFrame. Repare também que o código no método main(String[] args) faz parte das boas práticas SWING descritas no Web Site da ORACLE / SUN . Conclusão Utilize o Eclipse Kepler (4.3) sobre Java Platform (JDK 1.7_25) com o Google Plugin for Eclipse e o WindowBuilder Pro. Desenvolver interfaces gráficas Java em 5 minutos para : Swing, SWT, RCP, XWT e GWT com WindowBuilder Pro WYSIWYG, drag-and-drop interface. A moda é d'utilizar JavaFX que vem integrado no JDK : What Is JavaFX ? http://docs.oracle.com/javafx/2/overview/jfxpub-overview.htm Mais tarde mostro como fazer o resto , pan, zoom e muito mais com JavaFX e SWING é muito fácil ... Cordialmente Ernest Duarte Infelizmente devo de ter mesmo de utilizar o Java 2D, até porque tenho que desenhar "na" imagem. Já sei assim por alto como é que funciona, enquanto que Java FX não sei nada de nada, e visto que tenho prazo torna-se inviavel(só tenho semana e meia para ter algo a funcionar razoavelmente bem). Fiz uma "aldrabisse" para fazer o zoom o que acho não ser de todo correcto. Quando o programa inicia cria runnables para guardar em variaveis imagens já reduzidas por factores pre-definidos. Tirar zoom por tanto é apenas trocar de imagem. É muito mau fazer isso? Esta ajuda em especifico que estou a pedir é para uma aplicação que abre panoramas de alta resolução, e permite adicionar pontos de intresse nos mesmos, marcando-os na imagem com simbolos, os quais são interactivos para mostrarem mais informação. Tudo isso guardado numa base de dados SQLite que segue num package com cada grupo de imagens panoramicas(possivelmente farei um .tar com os dois numa extenção propria). Se tiver soluções melhores ou inisitir no Java FX tem de compensar realmente para este caso em especifico, pois porque não penso dar grande utilidade ao java de futuro. Perfiro linguagens compiladas em binario. Cumprimentos
Ernest Posted June 25, 2013 at 04:07 AM Report #514867 Posted June 25, 2013 at 04:07 AM Bom dia, Exemplo com AffineTransform.getScaleInstance quando utiliza o Slider (tem que esperar um bucado para o tratamento da Tranformação Afina) e também pode mover imagem com o rato. Agora falta meter os Markers interactivos como no Google Maps. import java.awt.Graphics2D; import java.awt.Point; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JScrollPane; import javax.swing.JSlider; import javax.swing.JViewport; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; /** * Exemplo de zooming e panning com jScrollPane * * @author Ernest Duarte * */ public class PanZoomImagem2 implements ChangeListener { BufferedImage image; JLabel label; public void stateChanged(ChangeEvent e) { int value = ((JSlider)e.getSource()).getValue(); double scale = value/100.0; BufferedImage scaled = getScaledImage(scale); label.setIcon(new ImageIcon(scaled)); label.revalidate(); } private BufferedImage getScaledImage(double scale) { int w = (int)(scale*image.getWidth()); int h = (int)(scale*image.getHeight()); BufferedImage bi = new BufferedImage(w, h, image.getType()); Graphics2D g2 = bi.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); AffineTransform at = AffineTransform.getScaleInstance(scale, scale); g2.drawRenderedImage(image, at); g2.dispose(); return bi; } private JLabel getContent(String nameImage) { createAnImage2(nameImage); label = new JLabel(new ImageIcon(image)); label.setHorizontalAlignment(JLabel.CENTER); return label; } private void createAnImage2(String nameImage) { try { image = ImageIO.read(new File(nameImage)); } catch (IOException e) { e.printStackTrace(); } } private JSlider getControl() { JSlider slider = new JSlider(JSlider.HORIZONTAL, 50, 200, 100); slider.setMajorTickSpacing(50); slider.setMinorTickSpacing(10); slider.setPaintTicks(true); slider.setPaintLabels(true); slider.addChangeListener(this); return slider; } static class HandScrollListener extends MouseAdapter { private final Point pp = new Point(); @Override public void mouseDragged(MouseEvent e) { JViewport vport = (JViewport)e.getSource(); JComponent label = (JComponent)vport.getView(); Point cp = e.getPoint(); Point vp = vport.getViewPosition(); vp.translate(pp.x-cp.x, pp.y-cp.y); label.scrollRectToVisible(new Rectangle(vp, vport.getSize())); vport.setViewPosition(vp); pp.setLocation(cp); } @Override public void mousePressed(MouseEvent e) { pp.setLocation(e.getPoint()); } } public static void main(String[] args) { PanZoomImagem2 app = new PanZoomImagem2(); JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JScrollPane jScrollPane = new JScrollPane(app.getContent("android_wallpaper_template_1920x1408.png")); //--------------- HandScrollListener JViewport vport = jScrollPane.getViewport(); MouseAdapter ma = new HandScrollListener(); vport.addMouseMotionListener(ma); vport.addMouseListener(ma); //------------- f.getContentPane().add(jScrollPane); f.getContentPane().add(app.getControl(), "Last"); f.setSize(400, 400); f.setLocation(200,200); f.setVisible(true); } } Cordialmente Ernest Duarte
claudiop Posted June 28, 2013 at 10:52 PM Author Report #516089 Posted June 28, 2013 at 10:52 PM Boas. Como novato que sou, demorei estes dois dias a tentar ler o seu codigo, até que pareçe que entendi(não me entendia com o ChangeListener). Tentei integrar o codigo dentro da estrutura do meu programa mas não estou a conseguir. Tenho as seguintes classes a dar uso ao seu codigo: Interface.java(Codigo encurtado para reflectir apenas o essencial): import java.awt.Color; import java.awt.Dimension; import java.awt.EventQueue; import javax.swing.JFrame; import javax.swing.JScrollPane; import java.awt.BorderLayout; import javax.swing.JSplitPane; import javax.swing.JPanel; import javax.swing.BoxLayout; import javax.swing.JLabel; import javax.swing.JSlider; import java.awt.FlowLayout; public class Interface { private JFrame mainFrame; public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try {Interface window = new Interface();window.mainFrame.setVisible(true); } catch (Exception e) { e.printStackTrace();} } }); } public Interface() {initialize();} private void initialize() { mainFrame = new JFrame(); mainFrame.setTitle("LXView"); mainFrame.setMinimumSize(new Dimension(800, 600)); mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mainFrame.setExtendedState(mainFrame.getExtendedState()| JFrame.MAXIMIZED_BOTH); mainFrame.getContentPane().setBackground(Color.WHITE); mainFrame.getContentPane().setLayout(new BorderLayout(0, 0)); JSplitPane splitPane = new JSplitPane(); splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT); splitPane.setOneTouchExpandable(true); splitPane.setBackground(Color.WHITE); mainFrame.getContentPane().add(splitPane, BorderLayout.CENTER); splitPane.setResizeWeight(0.99); JScrollPane scrollPane = new JScrollPane(); scrollPane.setEnabled(false); splitPane.setLeftComponent(scrollPane); Render topPane = new Render(); scrollPane.setViewportView(topPane); topPane.setLayout(new BoxLayout(topPane, BoxLayout.X_AXIS)); JPanel botPane = new JPanel(); splitPane.setRightComponent(botPane); botPane.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5)); JLabel zoomLevel = new JLabel("Zoom level:"); botPane.add(zoomLevel); JSlider slider = new JSlider(JSlider.HORIZONTAL, 25, 100, 100); slider.setMajorTickSpacing(15); slider.setMinorTickSpacing(5); slider.setPaintTicks(true); slider.setPaintLabels(true); slider.setPreferredSize(new Dimension(600,40)); botPane.add(slider); PanAndZoom zoomer=new PanAndZoom(topPane.getLabel()); slider.addChangeListener(zoomer); } } Render.java(idem aspas): import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JPanel; public class Render extends JPanel { JLabel envContainer; Render() { super(); ImageIcon imageIcon = new ImageIcon("/caminho/para/imagem"); JLabel envContainer = new JLabel(imageIcon); super.add(envContainer); } @Override public void paint(Graphics g) { super.paint(g); /*Renderizações*/ } public JLabel getLabel() { return envContainer; } } PanAndZoom.java import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JSlider; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; public class PanAndZoom implements ChangeListener { private JLabel label; private BufferedImage image; public PanAndZoom(JLabel lab){ this.label=lab; try { image = ImageIO.read(new File("/caminho/para/imagem")); } catch (IOException e) { e.printStackTrace(); } label.setIcon(new ImageIcon("/caminho/para/outra/imagem"));//Para testar trocar a imagem do icon. Dá erro! } public void stateChanged(ChangeEvent e) { int value = ((JSlider) e.getSource()).getValue(); double scale = value / 100.0; BufferedImage scaled = getScaledImage(scale); // Dá erro System.out.println("Scale:"+scale+" Value:"+value); label.setIcon(new ImageIcon(scaled)); label.revalidate(); } private BufferedImage getScaledImage(double scale) { int w = (int) (scale * image.getWidth()); int h = (int) (scale * image.getHeight()); BufferedImage bi = new BufferedImage(w, h, image.getType()); Graphics2D g2 = bi.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BICUBIC); AffineTransform at = AffineTransform.getScaleInstance(scale, scale); g2.drawRenderedImage(image, at); g2.dispose(); return bi; } } Os dois erros que tive (e assinalei), encontram-se relacionados com o acesso (ou falta dele) á JLabel que foi retornada pelo "getLabel()"[Render.java]. Se eu receber numa classe diferente uma LJabel já criada, e a associar a uma variavel, esse variavel não deveria de manter uma referencia ao JLabel da classe original? Cumprimentos e muito obrigado pelo seu codigo
Ernest Posted June 29, 2013 at 12:55 AM Report #516099 Posted June 29, 2013 at 12:55 AM (edited) Bom dia, Este programa tem só um erro de funcionamento : Tem um erro na classe Render.java : JLabel envContainer; // equivalente a JLabel envContainer = null; ..... JLabel envContainer = new JLabel(imageIcon); /// tem que tirar este JLabel em vermelho que está a esconder o primeiro lá encima ..... Se não, conclusão : getLabel() return NullPointerException ------------------------------- Chamar uma classe de Interface é possível mas não é muito claro na leitora de um programa Java ou até mesmo C#. Para um desenvolvedor java com mais de 10 anos de experiencia, até arrepia de ver esta frase : Interface window = new Interface(); Mesmo se está certo. Não é muito aconselhável de usar, já que existe uma palavra chave em Java : interface E que não se pode Instanciar uma interface em Java. Mesmo se está certo. Não é muito claro e pode criar confusões. Por que não escolher um outro nome como por exemplo VistaPrincipale.java ou MainFrame ou IHM ... etc. A escolha nos nomes corretos de variáveis é fundamental na resolução de um problema matemático e talvez ainda muito mais na implementação sem erros de um algoritmo informático. ------------------------------ Outra coisa importante é a arquitetura do programa informático. Um programa de computador é como uma casa, se não tiver uma boa arquitetura desde o início, pode entrar em colapso. Uma das regras é cada coisa no seu logar, separation of concerns (SoC). --------------------------- Agora Já não dá erro ! até funciona bem fluido e rápido no meu ordinateur (ordinator, computador). Pena não ter integrado a navegação com o rato do computador para navegar na imagem como no Google Maps. --------------------------------------- Para meter Point Of Interest (POI) nas imagens com um marker, como é o caso por exemplo no Google Maps. Uma solução simples é de preparar a imagem com pontos : Point Of Interest (POI) por exemplo provenientes de um ficheiro XML ( com as coordenadas latitude x, longitude y). Nessas posições (x , y) sobrepor uma pequena imagem (ou desenhá-la com Graphics g) e depois é so passar o rato por sima para ela reagir (gestão eventos... Design Pattern Observer) e mostrar informações suplementares sobre esse Point Of Interest (POI) . Depois é só fazer a mesma coisa com a nova imagem tratada com os POI. Com JAVA é muito fácil de programar :-) Cordialmente Ernest Duarte Edited June 29, 2013 at 01:03 AM by Ernest Duarte
claudiop Posted June 29, 2013 at 01:29 AM Author Report #516101 Posted June 29, 2013 at 01:29 AM (edited) Bom dia, Este programa tem só um erro de funcionamento : Tem um erro na classe Render.java : JLabel envContainer; // equivalente a JLabel envContainer = null; ..... JLabel envContainer = new JLabel(imageIcon); /// tem que tirar este JLabel em vermelho que está a esconder o primeiro lá encima ..... Se não, conclusão : getLabel() return NullPointerException ------------------------------- Chamar uma classe de Interface é possível mas não é muito claro na leitora de um programa Java ou até mesmo C#. Para um desenvolvedor java com mais de 10 anos de experiencia, até arrepia de ver esta frase : Interface window = new Interface(); Mesmo se está certo. Não é muito aconselhável de usar, já que existe uma palavra chave em Java : interface E que não se pode Instanciar uma interface em Java. Mesmo se está certo. Não é muito claro e pode criar confusões. Por que não escolher um outro nome como por exemplo VistaPrincipale.java ou MainFrame ou IHM ... etc. A escolha nos nomes corretos de variáveis é fundamental na resolução de um problema matemático e talvez ainda muito mais na implementação sem erros de um algoritmo informático. ------------------------------ Outra coisa importante é a arquitetura do programa informático. Um programa de computador é como uma casa, se não tiver uma boa arquitetura desde o início, pode entrar em colapso. Uma das regras é cada coisa no seu logar, separation of concerns (SoC). --------------------------- Agora Já não dá erro ! até funciona bem fluido e rápido no meu ordinateur (ordinator, computador). Pena não ter integrado a navegação com o rato do computador para navegar na imagem como no Google Maps. --------------------------------------- Para meter Point Of Interest (POI) nas imagens com um marker, como é o caso por exemplo no Google Maps. Uma solução simples é de preparar a imagem com pontos : Point Of Interest (POI) por exemplo provenientes de um ficheiro XML ( com as coordenadas latitude x, longitude y). Nessas posições (x , y) sobrepor uma pequena imagem (ou desenhá-la com Graphics g) e depois é so passar o rato por sima para ela reagir (gestão eventos... Design Pattern Observer) e mostrar informações suplementares sobre esse Point Of Interest (POI) . Depois é só fazer a mesma coisa com a nova imagem tratada com os POI. Com JAVA é muito fácil de programar :-) Cordialmente Ernest Duarte Muito obrigado por me ajudar a encontrar o erro. não fazia a minima ideia que uma classe pudesse ter duas variaveis com o mesmo nome independentes, mesmo que dentro de um metodo/constructor. Vou já fazer refactor nesse caso. Por acaso já tinha visto isso das "Interfaces", mas não me lembrei ou não tinha visto quando dei o nome á classe. A integração do pan vou faze-la tambem, mas só depois de fazer o sistema de Action Handlers(acho que é assim que se chama) que vão determinar onde é que o rato está, e se há o que fazer. Á partida devo de fazer isso a partir de uma list/array de cordenadas, e um listener na posição de rato sobre o painel da imagem. O pan só tinha um pequeno bug(que espero conseguir corrigir) que deixava a imagem ser arrastada indefinidamente para cima e para a esquerda, mas não é grave e devo de conseguir encontrar o erro com facilidade(espero eu). Sim, está relativamente fluido, mas as imagens a ser utilizadas não são nem de perto comparaveis em tamanho a essa. São imagens de 50+mpx com muitos MB's. Já exprimentei carregar uma e até não correu mal(cerca de 1 seg de delay), mas isso sou eu que apesar de não ter grande grafica, tenho um processador fortemente overclockado, que facilmente faz 5 computadores de escola. Isto não utiliza acelaração grafica pois não? Vou tratar agora(ou amanhã) disso do POI. EDIT ADD: Como poderei apagar os objectos que possam ter sido desenhados no paint() para os voltar a desenhar novamente noutras posições(devido ao zoom e ao pan)? Mais uma vez obrigado. Edited June 29, 2013 at 01:37 AM by claudiop
claudiop Posted June 29, 2013 at 04:44 PM Author Report #516171 Posted June 29, 2013 at 04:44 PM (edited) EDIT: Espero que ninguem tenha gasto a vista a ler o codigo que este post tinha. Desperdicio de QI total. Fiz merge da Classe Render, e da PanAndZoom. Background.java: public class Background extends JLabel implements ChangeListener { private ImageIcon background; private BufferedImage image; private double scale; public Background(JPanel parent){ super(); parent.add(this); try { image = ImageIO.read(new File("/example/background")); } catch (IOException e) { e.printStackTrace(); } this.background = new ImageIcon(image); this.setIcon(background); } public void stateChanged(ChangeEvent e) { int value = ((JSlider) e.getSource()).getValue(); this.scale = value / 100.0; BufferedImage scaled = getScaledImage(scale); this.setIcon(new ImageIcon(scaled)); this.revalidate(); this.repaint();//<<------ SOLUÇÂO MILAGROSA } private BufferedImage getScaledImage(double scale) { int w = (int) (scale * image.getWidth()); int h = (int) (scale * image.getHeight()); BufferedImage bi = new BufferedImage(w, h, image.getType()); Graphics2D g2 = bi.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BICUBIC); AffineTransform at = AffineTransform.getScaleInstance(scale, scale); g2.drawRenderedImage(image, at); g2.dispose(); return bi; } @Override public void paintComponent(Graphics g){ super.paint(g); /* * Componentes pintados com recurso á escala da imagem de fundo */ } Edited July 16, 2013 at 02:24 PM by Baderous geshi
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now