当 Image 分配给其下的 PictureBox 时标签消失
Label disappears when an Image is assigned to a PictureBox under it
我看过很多关于在 PictureBox 上添加标签的帖子,none 我看过的帖子解释了为什么我的标签在 PictureBox 上消失。
我用同样的问题从头开始创建了一个全新的标签,以排除我可能在没有意识到的情况下无意中更改了一些 属性。
首次加载窗体时,PictureBox 没有设置初始图像。
此时Label是可见的,但是Paint
事件没有被调用。
当 Imaged 被分配给 PictureBox 时,通过单击 Button,Label 不再可见并且仍然不会调用 Paint 事件。
但是,会调用 PictureBox 之外的另一个 Label 的 Paint 事件。
在设计器中我看到了这个:
Me.tabDesign.Controls.Add(Me.lblTitleTest)
因此,在 this post and this one 之后,我这样做:
Me.lblTitleTest.Location = Me.picMainImage.PointToClient(Me.tabDesign.PointToScreen(lblTitleTest.Location))
Me.lblTitleTest.Parent = Me.picMainImage
但是没有任何效果
接下来,我尝试使用 Paint 事件(如下),但该事件仅针对 PictureBox 外部 的标签调用。
如果 Label 位于 PictureBox 的顶部,则不会调用 Paint 事件:
Private Sub DrawTestTitleText(sender As Object, e As PaintEventArgs) Handles lblTitleTest.Paint
MsgBox("Drawing new test title")
TextRenderer.DrawText(e.Graphics, "Test Title", lblTitleTest.Font, New Point(10, 10), Color.Black)
End Sub
如果我将相同的代码与不同的标签一起使用,而不是在 PictureBox 上,绘制事件会按预期触发。
作为测试,我尝试将项目资源中的图像分配给 PictureBox。这没有帮助:Label 根本不可见,它的 Paint 事件也从未触发。
这里一定有一些细微的差别,我错过了。
我的目标是 .NET Framework 4.6.1。
将控件重新定位到保持相对位置的不同父容器:
假设,如在图形示例中,PictureBox.Location
是 (10, 100)
。在 Form Designer 中,一个 Label 位于 PictureBox 之上,它的 Location 是 (20, 110)
.
它相对于 PictureBox.ClientRectangle
的位置是 (10, 10) => (20-10, 110-100)
).
当然,如图所示,Label的背景颜色是继承的父窗体(控件的透明度是虚拟, Parent 的背景用作具有透明 BackColor 的子 Control 的背景。
▶ PictureBox 控件不是 ContainerControl or a ScrollableControl (it doesn't implement IContainerControl; i.e., doesn't have the WS_EX_CONTROLPARENT
样式集),因此当您在设计时将一个控件放置在其表面上时,它不会承载控件。
在运行时,您可以将控件的Parent
属性设置为PictureBox引用,以在这两个控件之间创建新的父子关系。
当您这样做时,需要考虑一些与控件布局相关的属性;在这种情况下 Location
属性.
设置父级不会更改子控件的 Location
值,该值现在是相对于新父级的。
▶ Label.Location
仍然是 (20, 110)
,但现在这个位置与 PictureBox.ClientRectangle
有关,而不是 Form 的。因此,如果您希望它保持其相对位置,则必须重新定位它。
您可以从子控件的Location
:
中减去新父控件的位置
[Label].Parent = [PictureBox]
[Label].Location = Point.Subtract([Label].Location, New Size([PictureBox].Left, [PictureBox].Top))
或者将Labels的客户坐标转换为Screen坐标,然后将Screen坐标应用到Parent的客户坐标:
[Label].Location = [PictureBox].PointToClient([Label].PointToScreen(Point.Empty))
当 Label 设置为新的 Parent 容器时,其背景也会适应 以适应新的 Parent 的背景,以保持明显的透明度。
在Form.Load
中(假设Label命名为label1
,PictureBox命名为pictureBox1
):
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
label1.Parent = pictureBox1
label1.Location = pictureBox1.PointToClient(label1.PointToScreen(Point.Empty))
' Or
' label1.Location = Point.Subtract(label1.Location, New Size(pictureBox1.Left, pictureBox1.Top))
End Sub
Design-Time: Run-Time:
您可以执行完全相同的操作,直接在 PictureBox 表面上绘制文本,在相同的位置,定义将在其中绘制文本的绘图矩形,与您之前使用的标签的位置和大小相同。
注意:
在这里,我使用 PictureBox Font
属性 作为 TextRenderer.DrawText 的 Font
参数。 PictureBox 隐藏了这个 属性,但它仍然可用(属于 Control
class);它继承自它的 Parent、Form 或其他容器。您当然可以指定任何其他字体。
参见 TextRenderer
的 TextFormatFlags,将文本放置在其他位置(例如,Top/Left)。
这里,TextFormatFlags.HorizontalCenter Or TextFormatFlags.VerticalCenter
用于将文本居中放置在绘图框的中间,由Paint事件中的drawingRect
定义。
private canvasFlags as TextFormatFlags = TextFormatFlags.HorizontalCenter Or
TextFormatFlags.VerticalCenter Or TextFormatFlags.NoPadding
private canvasText as String = "Some Text just for show"
private sub picCanvas_Paint(sender As object, e As PaintEventArgs) Handles pictureBox1.Paint
Dim pBox = DirectCast(sender, PictureBox)
Dim drawingRect = new Rectangle(10, 10, pBox.Width - 20, pBox.Font.Height + 4)
TextRenderer.DrawText(e.Graphics, canvasText, pBox.Font, drawingRect, Color.White, Color.Empty, canvasFlags)
End Sub
在 运行 时,Invalidate() PictureBox 当您想要重新绘制它时,例如,替换 Text。
结果:
我看过很多关于在 PictureBox 上添加标签的帖子,none 我看过的帖子解释了为什么我的标签在 PictureBox 上消失。
我用同样的问题从头开始创建了一个全新的标签,以排除我可能在没有意识到的情况下无意中更改了一些 属性。
首次加载窗体时,PictureBox 没有设置初始图像。
此时Label是可见的,但是Paint
事件没有被调用。
当 Imaged 被分配给 PictureBox 时,通过单击 Button,Label 不再可见并且仍然不会调用 Paint 事件。
但是,会调用 PictureBox 之外的另一个 Label 的 Paint 事件。
在设计器中我看到了这个:
Me.tabDesign.Controls.Add(Me.lblTitleTest)
因此,在 this post and this one 之后,我这样做:
Me.lblTitleTest.Location = Me.picMainImage.PointToClient(Me.tabDesign.PointToScreen(lblTitleTest.Location))
Me.lblTitleTest.Parent = Me.picMainImage
但是没有任何效果
接下来,我尝试使用 Paint 事件(如下),但该事件仅针对 PictureBox 外部 的标签调用。
如果 Label 位于 PictureBox 的顶部,则不会调用 Paint 事件:
Private Sub DrawTestTitleText(sender As Object, e As PaintEventArgs) Handles lblTitleTest.Paint
MsgBox("Drawing new test title")
TextRenderer.DrawText(e.Graphics, "Test Title", lblTitleTest.Font, New Point(10, 10), Color.Black)
End Sub
如果我将相同的代码与不同的标签一起使用,而不是在 PictureBox 上,绘制事件会按预期触发。
作为测试,我尝试将项目资源中的图像分配给 PictureBox。这没有帮助:Label 根本不可见,它的 Paint 事件也从未触发。
这里一定有一些细微的差别,我错过了。
我的目标是 .NET Framework 4.6.1。
将控件重新定位到保持相对位置的不同父容器:
假设,如在图形示例中,PictureBox.Location
是 (10, 100)
。在 Form Designer 中,一个 Label 位于 PictureBox 之上,它的 Location 是 (20, 110)
.
它相对于 PictureBox.ClientRectangle
的位置是 (10, 10) => (20-10, 110-100)
).
当然,如图所示,Label的背景颜色是继承的父窗体(控件的透明度是虚拟, Parent 的背景用作具有透明 BackColor 的子 Control 的背景。
▶ PictureBox 控件不是 ContainerControl or a ScrollableControl (it doesn't implement IContainerControl; i.e., doesn't have the WS_EX_CONTROLPARENT
样式集),因此当您在设计时将一个控件放置在其表面上时,它不会承载控件。
在运行时,您可以将控件的Parent
属性设置为PictureBox引用,以在这两个控件之间创建新的父子关系。
当您这样做时,需要考虑一些与控件布局相关的属性;在这种情况下 Location
属性.
设置父级不会更改子控件的 Location
值,该值现在是相对于新父级的。
▶ Label.Location
仍然是 (20, 110)
,但现在这个位置与 PictureBox.ClientRectangle
有关,而不是 Form 的。因此,如果您希望它保持其相对位置,则必须重新定位它。
您可以从子控件的
中减去新父控件的位置Location
:[Label].Parent = [PictureBox] [Label].Location = Point.Subtract([Label].Location, New Size([PictureBox].Left, [PictureBox].Top))
或者将Labels的客户坐标转换为Screen坐标,然后将Screen坐标应用到Parent的客户坐标:
[Label].Location = [PictureBox].PointToClient([Label].PointToScreen(Point.Empty))
当 Label 设置为新的 Parent 容器时,其背景也会适应 以适应新的 Parent 的背景,以保持明显的透明度。
在Form.Load
中(假设Label命名为label1
,PictureBox命名为pictureBox1
):
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
label1.Parent = pictureBox1
label1.Location = pictureBox1.PointToClient(label1.PointToScreen(Point.Empty))
' Or
' label1.Location = Point.Subtract(label1.Location, New Size(pictureBox1.Left, pictureBox1.Top))
End Sub
Design-Time: Run-Time:
您可以执行完全相同的操作,直接在 PictureBox 表面上绘制文本,在相同的位置,定义将在其中绘制文本的绘图矩形,与您之前使用的标签的位置和大小相同。
注意:
在这里,我使用 PictureBox Font
属性 作为 TextRenderer.DrawText 的 Font
参数。 PictureBox 隐藏了这个 属性,但它仍然可用(属于 Control
class);它继承自它的 Parent、Form 或其他容器。您当然可以指定任何其他字体。
参见 TextRenderer
的 TextFormatFlags,将文本放置在其他位置(例如,Top/Left)。
这里,TextFormatFlags.HorizontalCenter Or TextFormatFlags.VerticalCenter
用于将文本居中放置在绘图框的中间,由Paint事件中的drawingRect
定义。
private canvasFlags as TextFormatFlags = TextFormatFlags.HorizontalCenter Or
TextFormatFlags.VerticalCenter Or TextFormatFlags.NoPadding
private canvasText as String = "Some Text just for show"
private sub picCanvas_Paint(sender As object, e As PaintEventArgs) Handles pictureBox1.Paint
Dim pBox = DirectCast(sender, PictureBox)
Dim drawingRect = new Rectangle(10, 10, pBox.Width - 20, pBox.Font.Height + 4)
TextRenderer.DrawText(e.Graphics, canvasText, pBox.Font, drawingRect, Color.White, Color.Empty, canvasFlags)
End Sub
在 运行 时,Invalidate() PictureBox 当您想要重新绘制它时,例如,替换 Text。
结果: