AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / user-20938263

Luiz's questions

Martin Hope
Luiz
Asked: 2025-04-08 05:28:56 +0800 CST

Como desenhar juntas arredondadas (côncavas e convexas) em um PictureBox?

  • 6

Estou tentando configurar uma barra de progresso com uma caixa de imagem. Ela tem 4 cores e cantos e centros arredondados. Já consegui configurar a caixa de imagem com as cores e cantos arredondados, mas não consigo fazer o centro.

Este é um exemplo do que estou tentando reproduzir:

exemplo do que estou tentando reproduzir

Isso é o que eu já consegui fazer:

isso é o que eu já consegui fazer

Este é o código que estou usando:

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Dim pictureBox As New PictureBox()
    pictureBox.Size = New Size(280, 30)
    pictureBox.Location = New Point(10, 80)
    AddHandler pictureBox.Paint, AddressOf Me.PictureBox_Paint
    Me.Controls.Add(pictureBox)
End Sub

    Private Sub PictureBox_Paint(sender As Object, e As PaintEventArgs)
    Dim g As Graphics = e.Graphics
    g.SmoothingMode = SmoothingMode.AntiAlias ' Essencial para bordas suaves

    Dim pb As PictureBox = CType(sender, PictureBox)
    
    Dim area As Rectangle = pb.ClientRectangle
   
    Dim colors() As Color = {
        Color.FromArgb(85, 85, 135), 
        Color.FromArgb(217, 83, 79),  
        Color.FromArgb(240, 173, 78), 
        Color.FromArgb(91, 192, 222)  
    }
    Dim proportions() As Double = {0.25, 0.15, 0.35, 0.25}

    Dim totalWidth As Single = area.Width
    Dim totalHeight As Single = area.Height

    Dim cornerRadius As Single = CSng(Math.Min(totalWidth * 0.1, totalHeight / 2.0)) 
    If cornerRadius <= 0 Then cornerRadius = 1 

    Dim currentX As Single = area.X
    Dim numSegments As Integer = colors.Length

    
    For i As Integer = 0 To numSegments - 1
        Dim segmentWidth As Single
        If i = numSegments - 1 Then
            segmentWidth = (area.X + totalWidth) - currentX
        Else
            segmentWidth = CSng(totalWidth * proportions(i))
        End If

        If segmentWidth <= 0 Then Continue For

        Dim segmentRect As New RectangleF(currentX, area.Y, segmentWidth, totalHeight)

        Dim roundLeft As Boolean = (i = 0) 
        Dim roundRight As Boolean = (i = numSegments - 1) 

        Using segmentPath As GraphicsPath = CreateSegmentPath(segmentRect, cornerRadius, roundLeft, roundRight)
            Using segmentBrush As New SolidBrush(colors(i))
                g.FillPath(segmentBrush, segmentPath)
            End Using 
        End Using 

        currentX += segmentWidth
    Next
End Sub

Private Function CreateSegmentPath(rectF As RectangleF, radius As Single, makeLeftRound As Boolean, makeRightRound As Boolean) As GraphicsPath
    Dim path As New GraphicsPath()
    Dim diameter As Single = Math.Max(0, radius * 2) 

    If diameter > rectF.Width Then diameter = rectF.Width
    If diameter > rectF.Height Then diameter = rectF.Height
    radius = diameter / 2.0F 

    Dim Left As Single = rectF.Left
    Dim Top As Single = rectF.Top
    Dim Right As Single = rectF.Right
    Dim Bottom As Single = rectF.Bottom

    If radius <= 0 OrElse rectF.Width <= 0 OrElse rectF.Height <= 0 Then
        path.AddRectangle(rectF)
        Return path
    End If

    If makeLeftRound Then
        path.AddArc(Left, Top, diameter, diameter, 180, 90)
    Else
        ' Começa com uma linha reta no canto
        path.AddLine(Left, Top + radius, Left, Top) 
        path.AddLine(Left, Top, Left + radius, Top)
    End If

    path.AddLine(Left + radius, Top, Right - radius, Top)

    If makeRightRound Then
        path.AddArc(Right - diameter, Top, diameter, diameter, 270, 90)
    Else
        path.AddLine(Right - radius, Top, Right, Top) 
        path.AddLine(Right, Top, Right, Top + radius) 
    End If

    path.AddLine(Right, Top + radius, Right, Bottom - radius)

    If makeRightRound Then
        path.AddArc(Right - diameter, Bottom - diameter, diameter, diameter, 0, 90)
    Else
        path.AddLine(Right, Bottom - radius, Right, Bottom) ' Termina a linha direita
        path.AddLine(Right, Bottom, Right - radius, Bottom) ' Começa a linha inferior
    End If

    path.AddLine(Right - radius, Bottom, Left + radius, Bottom)

    If makeLeftRound Then
        path.AddArc(Left, Bottom - diameter, diameter, diameter, 90, 90)
    Else
        path.AddLine(Left + radius, Bottom, Left, Bottom) 
        path.AddLine(Left, Bottom, Left, Bottom - radius) 
    End If

    path.CloseFigure() 
    Return path
End Function

Agradeço qualquer ajuda para resolver este problema

Atualizar meu código:

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim pictureBox As New PictureBox()
pictureBox.Size = New Size(280, 30)
pictureBox.Location = New Point(10, 80)
AddHandler pictureBox.Paint, AddressOf Me.PictureBox_Paint
Me.Controls.Add(pictureBox)

End Sub

Private Sub PictureBox_Paint(sender As Object, e As PaintEventArgs)
Dim g As Graphics = e.Graphics
g.SmoothingMode = SmoothingMode.AntiAlias

Dim pb As PictureBox = CType(sender, PictureBox)
Dim area As Rectangle = pb.ClientRectangle
Dim colors As New List(Of Color) From {
    Color.FromArgb(70, 71, 117), ' Produtivo
    Color.FromArgb(210, 50, 45), ' Não Produtivo
    Color.FromArgb(237, 156, 40), ' Atenção
    Color.FromArgb(91, 192, 222) ' Não Definido
}
Dim proportions As New List(Of Double) From {0.25, 0.15, 0.35, 0.25}

Dim totalWidth As Single = area.Width
Dim totalHeight As Single = area.Height
Dim cornerRadius As Single = CSng(Math.Min(totalWidth * 0.1, totalHeight / 2.0))
If cornerRadius <= 0 Then cornerRadius = 1

Dim currentX As Single = area.X
paths.Clear() ' Limpar a lista antes de adicionar novos caminhos

' Criar os caminhos para cada segmento
For i As Integer = 0 To colors.Count - 1
    Dim segmentWidth As Single = CSng(totalWidth * proportions(i))
    If segmentWidth <= 0 Then Continue For

    Dim segmentRect As New RectangleF(currentX, area.Y, segmentWidth, totalHeight)
    Dim roundLeft As Boolean = (i = 0)
    Dim roundRight As Boolean = (i = colors.Count - 1)

    Dim segmentPath As GraphicsPath = CreateSegmentPath(segmentRect, cornerRadius, roundLeft, roundRight)
    paths.Add(segmentPath)

    currentX += segmentWidth
Next

' Pintar os caminhos de trás para frente
For i As Integer = paths.Count - 1 To 0 Step -1
    Using segmentBrush As New SolidBrush(colors(i))
        g.FillPath(segmentBrush, paths(i))
    End Using
Next
End Sub

Private Function CreateSegmentPath(rectF As RectangleF, radius As Single, makeLeftRound As Boolean, makeRightRound As Boolean) As GraphicsPath
Dim path As New GraphicsPath()
Dim diameter As Single = Math.Max(0, radius * 2)

If diameter > rectF.Width Then diameter = rectF.Width
If diameter > rectF.Height Then diameter = rectF.Height
radius = diameter / 2.0F

Dim Left As Single = rectF.Left
Dim Top As Single = rectF.Top
Dim Right As Single = rectF.Right
Dim Bottom As Single = rectF.Bottom

If radius <= 0 OrElse rectF.Width <= 0 OrElse rectF.Height <= 0 Then
    path.AddRectangle(rectF)
    Return path
End If

' --- Construção do Caminho ---
' Canto Superior Esquerdo
If makeLeftRound Then
    path.AddArc(Left, Top, diameter, diameter, 180, 90)
Else
    ' Começa com uma linha reta no canto
    path.AddLine(Left, Top + radius, Left, Top) ' Garante o ponto inicial correto
    path.AddLine(Left, Top, Left + radius, Top)
End If

' Linha Superior (entre os cantos/arcos)
path.AddLine(Left + radius, Top, Right - radius, Top)

' Canto Superior Direito
If makeRightRound Then
    path.AddArc(Right - diameter, Top, diameter, diameter, 270, 90)
Else
    path.AddLine(Right - radius, Top, Right, Top) ' Termina a linha superior
    path.AddLine(Right, Top, Right, Top + radius) ' Começa a linha direita
End If

' Linha Direita (Vertical)
path.AddLine(Right, Top + radius, Right, Bottom - radius)

' Canto Inferior Direito
If makeRightRound Then
    path.AddArc(Right - diameter, Bottom - diameter, diameter, diameter, 0, 90)
Else
    path.AddLine(Right, Bottom - radius, Right, Bottom) ' Termina a linha direita
    path.AddLine(Right, Bottom, Right - radius, Bottom) ' Começa a linha inferior
End If

' Linha Inferior
path.AddLine(Right - radius, Bottom, Left + radius, Bottom)

' Canto Inferior Esquerdo
If makeLeftRound Then
    path.AddArc(Left, Bottom - diameter, diameter, diameter, 90, 90)
Else
    path.AddLine(Left + radius, Bottom, Left, Bottom) ' Termina a linha inferior
    path.AddLine(Left, Bottom, Left, Bottom - radius) ' Começa a linha esquerda (para fechar)
End If

path.CloseFigure() ' Fecha o caminho conectando a última linha ao início
Return path
End Function
vb.net
  • 1 respostas
  • 97 Views

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Reformatar números, inserindo separadores em posições fixas

    • 6 respostas
  • Marko Smith

    Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não?

    • 2 respostas
  • Marko Smith

    Problema com extensão desinstalada automaticamente do VScode (tema Material)

    • 2 respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Martin Hope
    Fantastic Mr Fox Somente o tipo copiável não é aceito na implementação std::vector do MSVC 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant Encontre o próximo dia da semana usando o cronógrafo 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor O inicializador de membro do construtor pode incluir a inicialização de outro membro? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul O C++20 mudou para permitir a conversão de `type(&)[N]` de matriz de limites conhecidos para `type(&)[]` de matriz de limites desconhecidos? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann Como/por que {2,3,10} e {x,3,10} com x=2 são ordenados de forma diferente? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve