簡體   English   中英

如何在JScrollPane中實現圖形?

[英]How to implement graphics to JScrollPane?

目的是在窗口上繪制數十萬條垂直線,因此,我需要滾動條,因為將每一行分開的空間甚至都不是像素,所以不能選擇縮小。 我采用了在類中使用paint方法並將類和JScrollPane都添加到JFrame的方法。 無法解決,這就是為什么我采用了使用NetBeans JFrame Form的方法。 基本上,如何在帶有滾動條的面板中實現圖形方法? 我遇到的問題是我的值在打印機上正常,但是根本沒有窗口出現。 如果需要任何其他信息,請告訴我。 謝謝。

public class PedroGUI extends javax.swing.JFrame {
    public PedroGUI() {
        initComponents();
        draw();
    }
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        scroll = new javax.swing.JScrollPane();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        scroll.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
        scroll.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(scroll, javax.swing.GroupLayout.PREFERRED_SIZE, 429, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(123, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(scroll, javax.swing.GroupLayout.PREFERRED_SIZE, 267, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(86, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>                        


    public void draw() {
        Graphics g = scroll.getGraphics();
        g.setColor(Color.red);
        int bytes, samples, frequency;
        try {
            FileInputStream fis = new FileInputStream("./pepe.wav");
            BufferedInputStream bis = new BufferedInputStream(fis);
            byte[] data = new byte[128];
            bis.skip(44);
            samples = 0;
            while ((bytes = bis.read(data)) > 0) {
                for (int i = 0; i < bytes; i++) {
                    frequency = data[i] & 0xFF; 
                    System.out.println(samples + " " + frequency);
                    g.drawLine(samples, frequency + 300, samples, -frequency + 300);
                    samples++;
                }

            }
            bis.read(data);
            bis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String args[]) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                PedroGUI a = new PedroGUI();
                a.draw();
            }
        });
    }

    private javax.swing.JScrollPane scroll;

}

繪畫通常是通過重寫基於JComponent的類的paintComponent來實現的。 您不想做的是嘗試覆蓋JScrollPane paint/paintComponent ,並且最肯定不使用getGraphics

getGraphics返回組件上最后繪制的快照,如果嘗試對其進行繪制,則下次繪制組件時將丟棄該快照,因為Swing使用被動渲染算法,因此可以立即或在此完成將來有一些隨機時間(這就是為什么您應該使用paintComponent

繪畫也具有破壞性,也就是說,您應該從頭開始重新繪畫組件的狀態。

JScrollPane也是一個復合組件,即,有許多其他組件用於實現其功能(即JViewport

JScrollPane

您可能應該做的是創建一個自定義組件,從JPanel東西擴展它,並覆蓋它的paintComponent方法,並從其中生成圖形。

圖形

此示例還利用了Scrollable接口,該接口允許JScrollPane最初的布局小於組件的首選大小,這很好,因為組件可能非常寬。

這個例子也只是生成一個簡單的直方圖,但是你得到了jist

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;
import java.util.Map;
import java.util.TreeMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.Scrollable;

public class Main {

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Main();
            }
        });
    }

    public Main() {
        // For this example, I just randomised some data, you would
        // Need to load it yourself...
        int width = 256;
        int height = 256;
        int[][] data = new int[width][height];
        for (int c = 0; c < height; c++) {
            for (int r = 0; r < width; r++) {
                data[c][r] = (int) (256 * Math.random());
            }
        }
        Map<Integer, Integer> mapHistory = new TreeMap<Integer, Integer>();
        for (int c = 0; c < data.length; c++) {
            for (int r = 0; r < data[c].length; r++) {
                int value = data[c][r];
                int amount = 0;
                if (mapHistory.containsKey(value)) {
                    amount = mapHistory.get(value);
                    amount++;
                } else {
                    amount = 1;
                }
                mapHistory.put(value, amount);
            }
        }
        JFrame frame = new JFrame("Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());
        frame.add(new JScrollPane(new Graph(mapHistory)));
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    protected class Graph extends JPanel implements Scrollable {

        protected static final int MIN_BAR_WIDTH = 4;
        private Map<Integer, Integer> mapHistory;

        public Graph(Map<Integer, Integer> mapHistory) {
            this.mapHistory = mapHistory;
        }

        @Override
        public Dimension getPreferredSize() {
            int width = (mapHistory.size() * MIN_BAR_WIDTH) + 11;
            return new Dimension(width, 256);
        }

        @Override
        public Dimension getMinimumSize() {
            int width = (mapHistory.size() * MIN_BAR_WIDTH) + 11;
            return new Dimension(width, 128);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (mapHistory != null) {
                int xOffset = 5;
                int yOffset = 5;
                int width = getWidth() - 1 - (xOffset * 2);
                int height = getHeight() - 1 - (yOffset * 2);
                Graphics2D g2d = (Graphics2D) g.create();
                g2d.setColor(Color.DARK_GRAY);
                g2d.drawRect(xOffset, yOffset, width, height);
                int barWidth = Math.max(MIN_BAR_WIDTH,
                                (int) Math.floor((float) width
                                                / (float) mapHistory.size()));
                int maxValue = 0;
                for (Integer key : mapHistory.keySet()) {
                    int value = mapHistory.get(key);
                    maxValue = Math.max(maxValue, value);
                }
                int xPos = xOffset;
                for (Integer key : mapHistory.keySet()) {
                    int value = mapHistory.get(key);
                    int barHeight = Math.round(((float) value
                                    / (float) maxValue) * height);
                    g2d.setColor(new Color(key, key, key));
                    int yPos = height + yOffset - barHeight;
                    Rectangle2D bar = new Rectangle2D.Float(
                                    xPos, yPos, barWidth, barHeight);
                    g2d.fill(bar);
                    g2d.setColor(Color.DARK_GRAY);
                    g2d.draw(bar);
                    xPos += barWidth;
                }
                g2d.dispose();
            }
        }

        @Override
        public Dimension getPreferredScrollableViewportSize() {
            return new Dimension(512, 256);
        }

        @Override
        public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
            return 128;
        }

        @Override
        public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
            return 128;
        }

        @Override
        public boolean getScrollableTracksViewportWidth() {
            return getPreferredSize().width
                            <= getParent().getSize().width;
        }

        @Override
        public boolean getScrollableTracksViewportHeight() {
            return getPreferredSize().height
                            <= getParent().getSize().height;
        }
    }
}

有關更多詳細信息,請參見AWT和Swing中的 繪畫執行自定義繪畫以及如何使用滾動窗格

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM