java缩放图像绘制问题

Posted

技术标签:

【中文标题】java缩放图像绘制问题【英文标题】:java scaled image drawing problems 【发布时间】:2017-08-13 12:19:05 【问题描述】:

我搜索了一下,也问了更有经验的朋友,但没有找到任何东西。我正在尝试用java制作录音软件(例如fraps,bandicam)。基本上它可以正常工作,甚至非常好我注意到错误因为我每 2 毫秒制作一张图像并且效果很好=)我遇到的唯一问题是图像太大而无法在上面打印一个小 jframe (当然 1080p 屏幕不适合 600p 帧:/)所以我尝试使用 Image.getScaledInstance() 对其进行缩放,但是当我打印缩放后的图像时,它开始闪烁,因此您可以在短时间内看到图像时间(比如半秒)然后它就消失了。 (注意:当我使用调试器模式时,它工作得非常完美,而且我知道代码中的框架并不好,我还没有保存任何东西。我正在使用 Netbeans IDE)。

代码:

package Main;

import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;


/**
 *
 * @author Lucas
 */
public class MainClass 

    private DisplayFrame DF;
    private boolean isRecOn;
    private int counter = 0;
    private BufferedImage[] images;
    public void MainClass()
        DF = new DisplayFrame(this);
        DF.setVisible(true); 
    

    /**
     *
     */
    public void on_offRec(boolean on_off)

        this.isRecOn = on_off;
        if(on_off == true)
            try 
                this.doRecording();
             catch (AWTException ex) 
                Logger.getLogger(MainClass.class.getName()).log(Level.SEVERE, null, ex);
            
        
    
    private void doRecording() throws AWTException

        Robot robo = new Robot();


        BufferedImage bi = this.giveAFrame(robo);  
        boolean changeDisplay = DF.changeDisplay(bi);
        if(changeDisplay == true)
            Timer timy = new Timer();
            TimerTask tt = new TimerTask() 
                @Override
                public void run() 
                    try 
                        doRecording();
                     catch (AWTException ex) 
                        Logger.getLogger(MainClass.class.getName()).log(Level.SEVERE, null, ex);
                    
                
            ;
            timy.schedule(tt, 2);
        
        this.counter = this.counter +1;

    

    private BufferedImage giveAFrame(Robot robo)
        Dimension rectt = Toolkit.getDefaultToolkit().getScreenSize();
        Rectangle rect = new Rectangle(rectt.width,rectt.height);
        BufferedImage createScreenCapture = robo.createScreenCapture(rect);
        return createScreenCapture;
    

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) 
        MainClass mc = new MainClass();
        mc.MainClass();
    





package Main;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.image.BufferedImage;

/**
 *
 * @author Lucas
 */
public class DisplayFrame extends javax.swing.JFrame 

    private boolean isRecOn = false;
    private Object recall;
    /**
     * Creates new form DisplayFrame
     */
    public DisplayFrame(Object returner) 
        initComponents();

        recall = returner;



        this.getRootPane().addComponentListener(new ComponentAdapter() 
            public void componentResized(ComponentEvent e) 
                // This is only called when the user releases the mouse button.
                IGotResized(e);
            
        );
     


    private void IGotResized(ComponentEvent e)
        System.out.println("Testification rezised msg");
    
    public boolean changeDisplay(BufferedImage bi)
        Graphics g = this.getGraphics();
        Image i = bi.getScaledInstance(this.getWidth() - 20, this.getHeight() - jButton1.getX() - 10, Image.SCALE_FAST);
        g.drawImage(i,0 + 20 , 0+20, this);  
        return isRecOn;
    
    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() 

        jButton1 = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jButton1.setText("Start/Stop");
        jButton1.addActionListener(new java.awt.event.ActionListener() 
            public void actionPerformed(java.awt.event.ActionEvent evt) 
                jButton1ActionPerformed(evt);
            
        );

        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(jButton1)
                .addContainerGap(434, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap(353, Short.MAX_VALUE)
                .addComponent(jButton1)
                .addContainerGap())
        );

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

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt)                                          
        // TODO add your handling code here:
        if (isRecOn == true)
            isRecOn = false;
        else
            isRecOn = true;
            ((MainClass)(recall)).on_offRec(isRecOn); 
        
                                            

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) 
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try 
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) 
                if ("Nimbus".equals(info.getName())) 
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                
            
         catch (ClassNotFoundException ex) 
            java.util.logging.Logger.getLogger(DisplayFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
         catch (InstantiationException ex) 
            java.util.logging.Logger.getLogger(DisplayFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
         catch (IllegalAccessException ex) 
            java.util.logging.Logger.getLogger(DisplayFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
         catch (javax.swing.UnsupportedLookAndFeelException ex) 
            java.util.logging.Logger.getLogger(DisplayFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        
        //</editor-fold>

        /* Create and display the form */

    

    // Variables declaration - do not modify                     
    private javax.swing.JButton jButton1;
    // End of variables declaration                   

【问题讨论】:

【参考方案1】:

问题是,您在自定义函数中绘制图像。在 swing 中,每个组件都有自己的 paint(...) 函数,如果需要重绘组件,框架会调用该函数:

因此,您需要在 DisplayFrame 类中覆盖 paint(...) 函数。将您当前的 Image 保存为类参数并在覆盖的 paint(...) 函数中使用它。

【讨论】:

问题在于缩放,如果我评价它可以正常工作:/ 不,问题是,您的 JFrame 决定(不知道为什么)在您绘制图像后重绘,这就是为什么您可以暂时看到您的图像,但在它调用 paint(...) 之后再次 JFrame,您的图像消失了。您能否在应用了我的建议后显示您的代码,但没有成功?

以上是关于java缩放图像绘制问题的主要内容,如果未能解决你的问题,请参考以下文章

Java:JPanel 背景不缩放

.NET 在绘制到图形时缩放图像

在 ios 的滚动视图中绘制缩放的图像视图?

在图像视图上绘制矩形。图像无法正确缩放 - iOS

HTML5 Canvas ~ 使用绘制元素平滑快速缩放,而不是图像 ~ 如何?

使用 drawImage 缩放透明图像时出现故障