关于JPanel显示图片和添加组件的问题

关于JPanel显示图片和添加组件的问题,第1张

创建一个类ImagePanel继承JPanel

构造函数重写成要求一个参数(ImageIcon image)

然后对paintComponent进行Override。

附代码吧:

-------------------------------------ImagePanel.java-----------------------------------------------

import java.awt.Graphics

import java.awt.Dimension

import javax.swing.ImageIcon

import javax.swing.JPanel

public class ImagePanel extends JPanel{

private ImageIcon image = null

public ImagePanel( ImageIcon image ) {

this.image = image

this.setLayout(null)

}

protected void paintComponent( Graphics g ) {

setOpaque(true)

super.paintComponent(g)

Dimension dimension = getSize()

for ( int x = 0 x <dimension.width x+= image.getIconWidth() )

for ( int y = 0 y <dimension.height y+= image.getIconHeight())

g.drawImage(image.getImage(), x, y, null, null)

}

}

-----------------------------------------MainFrame.java---------------------------------------------

只给出部分代码

加载图片,参数是路径:ImageIcon image = new ImageIcon( 路径写在这里 )

再用这个图去实例化对象 mainPanel = new ImagePanel(image)

后面的 *** 作就和JPanel一样的。要加控件就是mainPanel.add(控件名)

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

我也刚学,是个菜,希望回答对你有帮助。

LZ关键问题是没有注意到图形在某位“位置”绘制后,如果该位置发生的移动,或其他图形遮挡了后会出现什么,如下图:

用其他什么东西,例如QQ遮挡 了一下原图形就没有了...因为在此之后没有人重新绘制了该图形,基于类似原因,即便你使用了Scoll,也无法看到后面的图形

你的程序我改造了一下,可以根据需求绘制图形,去掉Panel自带的HorizontalScroll,新增了一个hScrollBar(HorizontalScroll没有尝试成功,所以替换了,LZ可以多尝试下)

 private struct ImageContainerType

        {

            public Rectangle theImage     // 图形容器--矩形

            public SolidBrush theBrush    // 绘制该图形所用的画笔

        }

        // 绘制的图形的"容器"--这里用来存放绘制的矩形

        

        List<ImageContainerType> imageList

        // 用于控制绘图位置的全局变量

        int indexDraw = 0

        private void button1_Click(object sender, EventArgs e)

        {

            /*

                调整思路

             * 方案A:静态绘图

             * 1、将所有绘制的图形保存到imageList容器中

             * 2、在需要时再执行绘制,例如拖动Scoll时触发

             * 缺点:如果绘制的图形较多,将消耗大量内存

             * 优点:只需要执行一次图形创建过程,以后随时可以使用,节省CPU或GPU资源

             *      且算法简单

             * 

             * 方案B:动态绘图

             * 1、先绘制当前所需要的图形(在可见区间内)

             * 2、在需要时如Scoll,重新(在可见区间内)绘制所需要的图形

             */

            int[] nums = new int[10000]

            // 初始化图形容器

            imageList = new List<ImageContainerType>(100)

            ImageContainerType tempImage

            Random random = new Random() //随机数值

            for (int i = 0 i < 100 i++)

            {

                nums[i] = random.Next(0, 2)

            }

            for (int i = 0 i < 100 i++)

            {

                if (nums[i] == 1)

                {

                    SolidBrush r1 = new SolidBrush(Color.Red)//定义单色画刷    

                    Rectangle rect = new Rectangle(20 * i, 0, 10, 50)

                    //grap.FillRectangle(r1, rect)//填充这个矩形 

                    // 将当前图形存入容器

                    tempImage = new ImageContainerType()

                    tempImage.theBrush = new SolidBrush(Color.Red)

                    tempImage.theImage = new Rectangle(20 * i, 0, 10, 50)

                    imageList.Add(tempImage)

                }

                else

                {

                    SolidBrush b1 = new SolidBrush(Color.Blue)//定义单色画刷

                    Rectangle rect = new Rectangle(20 * i, 0, 10, 50)

                    //grap.FillRectangle(b1, rect)//填充这个矩形

                    tempImage = new ImageContainerType()

                    tempImage.theBrush = new SolidBrush(Color.Blue)

                    tempImage.theImage = new Rectangle(20 * i, 0, 10, 50)

                    imageList.Add(tempImage)

                }             

            }

            // [关键]设置Scorll的新值

            this.hScrollBar1.Maximum = 100

            // 绘制全部图形

            DrawImage(0, imageList.Count - 1)

            MessageBox.Show("绘制完成")

        }

        /// <summary>

        /// 实际的图形绘制方法

        /// </summary>

        /// <param name="start">所需绘制图形的起始编号</param>

        /// <param name="end">所需绘制图形的结束编号,如果end在start则绘制所有剩下图形</param>

        void DrawImage(int start, int end)

        { 

            // 1、判定绘图容器是否存在

            if (imageList == null || imageList.Count <= 0)

            {

                MessageBox.Show("还没有生成图形")

                return

            }

            // 2、绘图区间判定

            if (start >= imageList.Count || end >= imageList.Count)

            {

                MessageBox.Show("不在有效绘图区间")

                return

            }

            // 3、

            if (start <= end)

            { 

                // 绘制从起始位置,到结束位置所有图形

                end = imageList.Count - 1

            }

            // 4、绘制图形

            Graphics grap = pChart.CreateGraphics()

            grap.Clear(Color.White)

            Pen blue = new Pen(Color.Blue)

            Pen red = new Pen(Color.Red)

            for(int index=startindex<= endindex++)

            {

                grap.FillRectangle(imageList[index].theBrush, imageList[index].theImage)

            }            

        }

        /// <summary>

        /// 在Scroll实际中重绘Panel内容

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="e"></param>

        private void hScrollBar1_Scroll(object sender, ScrollEventArgs e)

        {

            // 每次重绘"当前位置"直至结尾的所有图形

            DrawImage(e.NewValue, imageList.Count - 1)

        }

得到的效果是:

你可以看到,Scoll正确发挥了作用,但貌似图形不正确阿....前面的没有了?

原因在于现有的重绘访法是

// 每次重绘"当前位置"直至结尾的所有图形

DrawImage(e.NewValue, imageList.Count - 1)

而在imageList容器中存放的图形其坐标已经固定了,因此绘制结果也就可以预期了——这距离使用Scoll拖动图形距离不远了:>

其实关键就是图形和界面之间相对位置的处理了——界面是静止的,那么只有让图动起来,看我的改造:

注意上面两个图形的坐标,0-99和9~99,然后看相应的图形。的确界面没动,但图形动了,看起来就像是Panel向右滑动了10个单位一样。修改Scoll事件中的绘图方法就可以达到所需要的效果了

        /// <summary>

        /// 在Scroll实际中重绘Panel内容

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="e"></param>

        private void hScrollBar1_Scroll(object sender, ScrollEventArgs e)

        {

            int theValue = e.NewValue

            int theNewImageX_Index = 0

            // 要想实现“动态效果”的关键是重新计算图形与“静止”的界面

            // 之间的相对位置,即“界面不动”图形动(我不动那就麻烦你动一下了:>)

            // 这将消耗一定的CPU资源

            // --尝试将图形的位置根据当前"位置"进行移动

            // --将当前图形设定为"相对于界面"的第一个图形,后面的图形依次+1

            for (int index = theValue index < imageList.Count index++)

            {

                ImageContainerType temp = new ImageContainerType()

                temp.theImage = new Rectangle(20 * theNewImageX_Index, 0, 10, 50)

                temp.theBrush = imageList[index].theBrush

                imageList[index] = temp

                theNewImageX_Index++

            }

            // 然后重新绘制图形

            DrawImage(theValue, imageList.Count - 1)

        }

这里最关键的就是重新计算图形的坐标

new Rectangle(20 * theNewImageX_Index, 0, 10, 50)


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/bake/11787706.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-18
下一篇2023-05-18

发表评论

登录后才能评论

评论列表(0条)

    保存