在 C# 中使用滑块和依赖属性创建和使用新画笔或颜色

发布于 2024-10-02 16:57:30 字数 11669 浏览 4 评论 0原文

我正在开发一个基本的 WPF“绘画”应用程序项目。我有三个选项,画一个椭圆,画一条线,或者画一个“形状”(填充封闭部分的线)。这三个选项用单选按钮表示。我已经完成了这部分工作。这是一个示例屏幕截图:

https://i.sstatic.net/naPyI.jpg

基本上我的内容现在需要做的是,当用户更改 R、G、B 和 A(不透明度/alpha)的滑块时,应更新显示新颜色的小预览区域,并且应将该颜色设置为线条或填充颜色,取决于更改哪组滑块。 所有这些都需要通过数据绑定来完成。

我不太确定如何最好地解决这个问题。我应该为每个滑块(RGBA)设置单独的值并将这些值传递给 Color.FromArgb(R,G,B,A) 吗?

编辑:这是我

使用系统的代码; 使用 System.Collections.Generic; 使用 System.Linq; 使用系统文本; 使用系统.Windows; 使用 System.Windows.Controls; 使用 System.Windows.Data; 使用 System.Windows.Documents; 使用 System.Windows.Input; 使用 System.Windows.Media; 使用 System.Windows.Media.Imaging; 使用系统.Windows.导航; 使用 System.Windows.Shapes; 使用 System.ComponentModel;

namespace WpfPaint
{
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public bool start = false;
        public Ellipse myEllipse;
        public Polyline myLine;
        public Line myRegLine = new Line();
        public double xPos;
        public double yPos;

        public MainWindow()
        {
            InitializeComponent();
            MyCanvas.Children.Add(myRegLine);
        }

        private void MyCanvas_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            if (this.ellipse.IsChecked ?? false)
            {
                if (start)
                {
                    start = !start;
                    myEllipse = null;
                }
                else
                {
                    start = true;
                    myEllipse = new Ellipse();
                    xPos = e.GetPosition(MyCanvas).X;
                    yPos = e.GetPosition(MyCanvas).Y;

                    MyCanvas.Children.Add(myEllipse);
                    myEllipse.StrokeThickness = 5;
                    if (comboBox2.Text == "Red")
                    {
                        myEllipse.Fill = Brushes.Red;
                        fillR.Value = 255;
                        fillG.Value = 0;
                        fillB.Value = 0;
                    }
                    else if (comboBox2.Text == "Green")
                    {
                        myEllipse.Fill = Brushes.Green;
                        fillR.Value = 0;
                        fillG.Value = 255;
                        fillB.Value = 0;
                    }
                    else if (comboBox2.Text == "Blue")
                    {
                        myEllipse.Fill = Brushes.Blue;
                        fillR.Value = 0;
                        fillG.Value = 0;
                        fillB.Value = 255;
                    }

                    if (comboBox1.Text == "Red")
                    {
                        myEllipse.Stroke = Brushes.Red;
                        lineR.Value = 255;
                        lineG.Value = 0;
                        lineB.Value = 0;
                    }
                    else if (comboBox1.Text == "Green")
                    {
                        myEllipse.Stroke = Brushes.Green;
                        lineR.Value = 0;
                        lineG.Value = 255;
                        lineB.Value = 0;
                    }
                    else if (comboBox1.Text == "Blue")
                    {
                        myEllipse.Stroke = Brushes.Blue;
                        lineR.Value = 0;
                        lineG.Value = 0;
                        lineB.Value = 255;
                    }
                }
            }
            else
            {
                switch (e.ClickCount)
                {
                    case 1:
                        if (myLine == null)
                        {
                            myLine = new Polyline();
                            MyCanvas.Children.Add(myLine);
                            myLine.StrokeThickness = 5;
                            if (comboBox1.Text == "Red")
                            {

                                myLine.Stroke = Brushes.Red;
                                lineR.Value = 255;
                                lineG.Value = 0;
                                lineB.Value = 0;
                            }
                            else if (comboBox1.Text == "Green")
                            {

                                myLine.Stroke = Brushes.Green;
                                lineR.Value = 0;
                                lineG.Value = 255;
                                lineB.Value = 0;
                            }
                            else if (comboBox1.Text == "Blue")
                            {

                                myLine.Stroke = Brushes.Blue;
                                lineR.Value = 0;
                                lineG.Value = 0;
                                lineB.Value = 255;                                
                            }

                            if (this.shape.IsChecked ?? false)
                            {
                                if (comboBox2.Text == "Red")
                                {                                    
                                    myLine.Fill = Brushes.Red;
                                    fillR.Value = 255;
                                    fillG.Value = 0;
                                    fillB.Value = 0;
                                }
                                else if (comboBox2.Text == "Green")
                                {                                    
                                    myLine.Fill = Brushes.Green;
                                    fillR.Value = 0;
                                    fillG.Value = 255;
                                    fillB.Value = 0;
                                }
                                else if (comboBox2.Text == "Blue")
                                {                                    
                                    myLine.Fill = Brushes.Blue;
                                    fillR.Value = 0;
                                    fillG.Value = 0;
                                    fillB.Value = 255;
                                }
                            }


                        }

                        myLine.Points.Add(e.GetPosition(MyCanvas));
                        e.Handled = true;

                        break;
                    case 2:
                        myLine = null;
                        myRegLine = new Line();
                        MyCanvas.Children.Add(myRegLine);
                        break;

                }

            }
        }

        private void MyCanvas_PreviewMouseMove(object sender, MouseEventArgs e)
        {
            if (start)
            {
                myEllipse.Height = Math.Abs(e.GetPosition(MyCanvas).X - xPos) * 2;
                myEllipse.Width = Math.Abs(e.GetPosition(MyCanvas).X - xPos) * 2;

                Canvas.SetTop(myEllipse, ((yPos) - myEllipse.Height / 2));
                Canvas.SetLeft(myEllipse, ((xPos) - myEllipse.Width / 2));
            }

            else
            {
                if (myLine != null)
                {
                    myRegLine.Stroke = myLine.Stroke;
                    myRegLine.X1 = myLine.Points.Last().X;
                    myRegLine.Y1 = myLine.Points.Last().Y;
                    myRegLine.X2 = e.GetPosition(MyCanvas).X;
                    myRegLine.Y2 = e.GetPosition(MyCanvas).Y;
                }
            }
        }

        private void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

        }

        private void comboBox2_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

        }
    }
}

这是我的 XAML

<Window x:Class="WpfPaint.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <RadioButton Content="Line" Height="16" HorizontalAlignment="Left" Margin="12,10,0,0" Name="line" GroupName="options" VerticalAlignment="Top" IsChecked="True" />
    <RadioButton Content="Shape" Height="16" HorizontalAlignment="Left" Margin="12,34,0,0" Name="shape" GroupName="options" VerticalAlignment="Top" />
    <RadioButton Content="Ellipse" Height="16" HorizontalAlignment="Left" Margin="12,56,0,0" Name="ellipse" GroupName="options" VerticalAlignment="Top" />
    <Label Content="R" Margin="210,5,270,0" Height="31" VerticalAlignment="Top" />
    <Slider Height="23" HorizontalAlignment="Left" Margin="229,5,0,0" Name="lineR" VerticalAlignment="Top" Width="50" IsMoveToPointEnabled="False" Interval="1" IsSelectionRangeEnabled="False" Maximum="255" />
    <Slider Height="23" Margin="306,5,147,0" Name="lineG" VerticalAlignment="Top" IsMoveToPointEnabled="False" Interval="1" Maximum="255" />
    <Label Content="G" Margin="282,3,203,0" Height="30" VerticalAlignment="Top" />
    <Slider Height="23" HorizontalAlignment="Left" Margin="380,5,0,0" Name="lineB" VerticalAlignment="Top" Width="50" Interval="1" Maximum="255" />
    <Label Content="B" Margin="358,3,129,280"/>
    <Slider Height="23" HorizontalAlignment="Left" Margin="453,5,0,0" Name="lineA" VerticalAlignment="Top" Width="50" Interval="1" Maximum="255" Value="255" />
    <Label Content="A" Margin="428,3,56,0" Height="28" VerticalAlignment="Top" />
    <Canvas Name="MyCanvas" Background="#FFDADADA" Margin="0,76,0,0" PreviewMouseDown="MyCanvas_PreviewMouseDown" PreviewMouseMove="MyCanvas_PreviewMouseMove"></Canvas>
    <ComboBox Height="23" HorizontalAlignment="Left" Margin="127,5,0,0" Name="comboBox1" VerticalAlignment="Top" Width="70" SelectionChanged="comboBox1_SelectionChanged">
        <ComboBoxItem Content="Red" IsSelected="True" />
        <ComboBoxItem Content="Green" />
        <ComboBoxItem Content="Blue" />
    </ComboBox>
    <Label Content="Line" Height="28" HorizontalAlignment="Left" Margin="89,3,0,0" Name="label1" VerticalAlignment="Top" />
    <Label Content="Fill" Height="28" HorizontalAlignment="Left" Margin="96,42,0,0" Name="label2" VerticalAlignment="Top" />
    <ComboBox Height="23" HorizontalAlignment="Left" Margin="127,44,0,0" Name="comboBox2" VerticalAlignment="Top" Width="70" SelectionChanged="comboBox2_SelectionChanged">
        <ComboBoxItem Content="Red" IsSelected="True" />
        <ComboBoxItem Content="Green" />
        <ComboBoxItem Content="Blue" />
    </ComboBox>
    <Label Content="R" Margin="210,42,270,238" />
    <Slider Height="23" HorizontalAlignment="Left" IsMoveToPointEnabled="False" Margin="229,44,0,0" Name="fillR" VerticalAlignment="Top" Width="50" Maximum="255" Interval="1" />
    <Slider Height="23" HorizontalAlignment="Left" IsMoveToPointEnabled="False" Margin="306,44,0,0" Name="fillG" VerticalAlignment="Top" Width="50" Maximum="255" Interval="1" />
    <Label Content="G" Margin="282,40,203,241" />
    <Slider Height="23" HorizontalAlignment="Left" Margin="380,44,0,0" Name="fillB" VerticalAlignment="Top" Width="50" Maximum="255" Interval="1" />
    <Label Content="B" Margin="358,42,0,241" HorizontalAlignment="Left" Width="16" />
    <Slider Height="23" HorizontalAlignment="Left" Margin="453,44,0,0" Name="fillA" VerticalAlignment="Top" Width="50" Value="255" Interval="1" Maximum="255" />
    <Label Content="A" Margin="428,42,56,241" />
</Grid>

I'm working on a project which is a basic WPF "Paint" app. I have three options, draw an Ellipse, draw a Line, or draw a 'shape' (a line where closed sections are filled in). These three options are represented with radio buttons. I have up to this part working. Here's an example screenshot:

https://i.sstatic.net/naPyI.jpg

Basically what I need to do now is, when the user changes the sliders for R, G, B, and A (opacity / alpha), a small preview area showing the new color should be updated, and that color should be set as the line or fill color, depending on which group of sliders is changed. All of this needs to be done with data binding.

I'm not really sure as to to best approach this problem. Should I have individual values for each slider (RGBA) and pass those values into Color.FromArgb(R,G,B,A)??

EDIT: Here is my code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace WpfPaint
{
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public bool start = false;
        public Ellipse myEllipse;
        public Polyline myLine;
        public Line myRegLine = new Line();
        public double xPos;
        public double yPos;

        public MainWindow()
        {
            InitializeComponent();
            MyCanvas.Children.Add(myRegLine);
        }

        private void MyCanvas_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            if (this.ellipse.IsChecked ?? false)
            {
                if (start)
                {
                    start = !start;
                    myEllipse = null;
                }
                else
                {
                    start = true;
                    myEllipse = new Ellipse();
                    xPos = e.GetPosition(MyCanvas).X;
                    yPos = e.GetPosition(MyCanvas).Y;

                    MyCanvas.Children.Add(myEllipse);
                    myEllipse.StrokeThickness = 5;
                    if (comboBox2.Text == "Red")
                    {
                        myEllipse.Fill = Brushes.Red;
                        fillR.Value = 255;
                        fillG.Value = 0;
                        fillB.Value = 0;
                    }
                    else if (comboBox2.Text == "Green")
                    {
                        myEllipse.Fill = Brushes.Green;
                        fillR.Value = 0;
                        fillG.Value = 255;
                        fillB.Value = 0;
                    }
                    else if (comboBox2.Text == "Blue")
                    {
                        myEllipse.Fill = Brushes.Blue;
                        fillR.Value = 0;
                        fillG.Value = 0;
                        fillB.Value = 255;
                    }

                    if (comboBox1.Text == "Red")
                    {
                        myEllipse.Stroke = Brushes.Red;
                        lineR.Value = 255;
                        lineG.Value = 0;
                        lineB.Value = 0;
                    }
                    else if (comboBox1.Text == "Green")
                    {
                        myEllipse.Stroke = Brushes.Green;
                        lineR.Value = 0;
                        lineG.Value = 255;
                        lineB.Value = 0;
                    }
                    else if (comboBox1.Text == "Blue")
                    {
                        myEllipse.Stroke = Brushes.Blue;
                        lineR.Value = 0;
                        lineG.Value = 0;
                        lineB.Value = 255;
                    }
                }
            }
            else
            {
                switch (e.ClickCount)
                {
                    case 1:
                        if (myLine == null)
                        {
                            myLine = new Polyline();
                            MyCanvas.Children.Add(myLine);
                            myLine.StrokeThickness = 5;
                            if (comboBox1.Text == "Red")
                            {

                                myLine.Stroke = Brushes.Red;
                                lineR.Value = 255;
                                lineG.Value = 0;
                                lineB.Value = 0;
                            }
                            else if (comboBox1.Text == "Green")
                            {

                                myLine.Stroke = Brushes.Green;
                                lineR.Value = 0;
                                lineG.Value = 255;
                                lineB.Value = 0;
                            }
                            else if (comboBox1.Text == "Blue")
                            {

                                myLine.Stroke = Brushes.Blue;
                                lineR.Value = 0;
                                lineG.Value = 0;
                                lineB.Value = 255;                                
                            }

                            if (this.shape.IsChecked ?? false)
                            {
                                if (comboBox2.Text == "Red")
                                {                                    
                                    myLine.Fill = Brushes.Red;
                                    fillR.Value = 255;
                                    fillG.Value = 0;
                                    fillB.Value = 0;
                                }
                                else if (comboBox2.Text == "Green")
                                {                                    
                                    myLine.Fill = Brushes.Green;
                                    fillR.Value = 0;
                                    fillG.Value = 255;
                                    fillB.Value = 0;
                                }
                                else if (comboBox2.Text == "Blue")
                                {                                    
                                    myLine.Fill = Brushes.Blue;
                                    fillR.Value = 0;
                                    fillG.Value = 0;
                                    fillB.Value = 255;
                                }
                            }


                        }

                        myLine.Points.Add(e.GetPosition(MyCanvas));
                        e.Handled = true;

                        break;
                    case 2:
                        myLine = null;
                        myRegLine = new Line();
                        MyCanvas.Children.Add(myRegLine);
                        break;

                }

            }
        }

        private void MyCanvas_PreviewMouseMove(object sender, MouseEventArgs e)
        {
            if (start)
            {
                myEllipse.Height = Math.Abs(e.GetPosition(MyCanvas).X - xPos) * 2;
                myEllipse.Width = Math.Abs(e.GetPosition(MyCanvas).X - xPos) * 2;

                Canvas.SetTop(myEllipse, ((yPos) - myEllipse.Height / 2));
                Canvas.SetLeft(myEllipse, ((xPos) - myEllipse.Width / 2));
            }

            else
            {
                if (myLine != null)
                {
                    myRegLine.Stroke = myLine.Stroke;
                    myRegLine.X1 = myLine.Points.Last().X;
                    myRegLine.Y1 = myLine.Points.Last().Y;
                    myRegLine.X2 = e.GetPosition(MyCanvas).X;
                    myRegLine.Y2 = e.GetPosition(MyCanvas).Y;
                }
            }
        }

        private void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

        }

        private void comboBox2_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

        }
    }
}

and here is my XAML

<Window x:Class="WpfPaint.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <RadioButton Content="Line" Height="16" HorizontalAlignment="Left" Margin="12,10,0,0" Name="line" GroupName="options" VerticalAlignment="Top" IsChecked="True" />
    <RadioButton Content="Shape" Height="16" HorizontalAlignment="Left" Margin="12,34,0,0" Name="shape" GroupName="options" VerticalAlignment="Top" />
    <RadioButton Content="Ellipse" Height="16" HorizontalAlignment="Left" Margin="12,56,0,0" Name="ellipse" GroupName="options" VerticalAlignment="Top" />
    <Label Content="R" Margin="210,5,270,0" Height="31" VerticalAlignment="Top" />
    <Slider Height="23" HorizontalAlignment="Left" Margin="229,5,0,0" Name="lineR" VerticalAlignment="Top" Width="50" IsMoveToPointEnabled="False" Interval="1" IsSelectionRangeEnabled="False" Maximum="255" />
    <Slider Height="23" Margin="306,5,147,0" Name="lineG" VerticalAlignment="Top" IsMoveToPointEnabled="False" Interval="1" Maximum="255" />
    <Label Content="G" Margin="282,3,203,0" Height="30" VerticalAlignment="Top" />
    <Slider Height="23" HorizontalAlignment="Left" Margin="380,5,0,0" Name="lineB" VerticalAlignment="Top" Width="50" Interval="1" Maximum="255" />
    <Label Content="B" Margin="358,3,129,280"/>
    <Slider Height="23" HorizontalAlignment="Left" Margin="453,5,0,0" Name="lineA" VerticalAlignment="Top" Width="50" Interval="1" Maximum="255" Value="255" />
    <Label Content="A" Margin="428,3,56,0" Height="28" VerticalAlignment="Top" />
    <Canvas Name="MyCanvas" Background="#FFDADADA" Margin="0,76,0,0" PreviewMouseDown="MyCanvas_PreviewMouseDown" PreviewMouseMove="MyCanvas_PreviewMouseMove"></Canvas>
    <ComboBox Height="23" HorizontalAlignment="Left" Margin="127,5,0,0" Name="comboBox1" VerticalAlignment="Top" Width="70" SelectionChanged="comboBox1_SelectionChanged">
        <ComboBoxItem Content="Red" IsSelected="True" />
        <ComboBoxItem Content="Green" />
        <ComboBoxItem Content="Blue" />
    </ComboBox>
    <Label Content="Line" Height="28" HorizontalAlignment="Left" Margin="89,3,0,0" Name="label1" VerticalAlignment="Top" />
    <Label Content="Fill" Height="28" HorizontalAlignment="Left" Margin="96,42,0,0" Name="label2" VerticalAlignment="Top" />
    <ComboBox Height="23" HorizontalAlignment="Left" Margin="127,44,0,0" Name="comboBox2" VerticalAlignment="Top" Width="70" SelectionChanged="comboBox2_SelectionChanged">
        <ComboBoxItem Content="Red" IsSelected="True" />
        <ComboBoxItem Content="Green" />
        <ComboBoxItem Content="Blue" />
    </ComboBox>
    <Label Content="R" Margin="210,42,270,238" />
    <Slider Height="23" HorizontalAlignment="Left" IsMoveToPointEnabled="False" Margin="229,44,0,0" Name="fillR" VerticalAlignment="Top" Width="50" Maximum="255" Interval="1" />
    <Slider Height="23" HorizontalAlignment="Left" IsMoveToPointEnabled="False" Margin="306,44,0,0" Name="fillG" VerticalAlignment="Top" Width="50" Maximum="255" Interval="1" />
    <Label Content="G" Margin="282,40,203,241" />
    <Slider Height="23" HorizontalAlignment="Left" Margin="380,44,0,0" Name="fillB" VerticalAlignment="Top" Width="50" Maximum="255" Interval="1" />
    <Label Content="B" Margin="358,42,0,241" HorizontalAlignment="Left" Width="16" />
    <Slider Height="23" HorizontalAlignment="Left" Margin="453,44,0,0" Name="fillA" VerticalAlignment="Top" Width="50" Value="255" Interval="1" Maximum="255" />
    <Label Content="A" Margin="428,42,56,241" />
</Grid>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

静谧幽蓝 2024-10-09 16:57:30

不确定这是否是最好的方法,但您的视图模型中可以有 5 个公共属性:
一个用于 Alpha,一个用于红色,一个用于绿色,一个用于蓝色,还有一个用户定义的结构,您将使用该结构将 4 个值“分组”在一起(我们称之为 FillValue)。将 4 个滑块绑定到 Alpha、红色、绿色和蓝色。在这 4 个属性的设置器中,您可以在 FillValue 中设置相应的字段,然后为这两个属性调用 NotifyPropertyChanged。像这样的事情:

    public double Red
    {
        get { return FillValue.Red; }
        set
        {
            FillValue.Red = value;
            NotifyPropertyChanged("Red");
            NotifyPropertyChanged("FillValue");
        }
    }

然后将预览的填充属性绑定到 FillValue 并添加一个转换器以将 FillValue 转换为画笔。绑定看起来像这样:

<StackPanel>    
    <StackPanel.Resources>
        <RGBExample:FillValueCvtr x:Key="ColorCvtr"/>
    </StackPanel.Resources>

    <Rectangle Fill="{Binding FillValue, Converter={StaticResource ColorCvtr}}"/>
</StackPanel>

Not sure if this is the best way to do it but you can have 5 public properties in your viewmodel:
one for Alpha, one for Red, one for Green, one for Blue, and one user defined structure that you will use to "group" the 4 values together (let's call it FillValue). Bind your 4 sliders to Alpha, Red, Green, and Blue. in the setters for those 4 properties, you set the corresponding field in FillValue then call NotifyPropertyChanged for both properties. Something like this:

    public double Red
    {
        get { return FillValue.Red; }
        set
        {
            FillValue.Red = value;
            NotifyPropertyChanged("Red");
            NotifyPropertyChanged("FillValue");
        }
    }

Then bind your preview's fill property to FillValue and add a converter to convert the FillValue to a brush. The binding will look something like this:

<StackPanel>    
    <StackPanel.Resources>
        <RGBExample:FillValueCvtr x:Key="ColorCvtr"/>
    </StackPanel.Resources>

    <Rectangle Fill="{Binding FillValue, Converter={StaticResource ColorCvtr}}"/>
</StackPanel>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文