【问题标题】:Picture Puzzle: Spaces/Gaps between Grid Rows图片拼图:网格行之间的空间/间隙
【发布时间】:2012-11-21 23:25:39
【问题描述】:

我试着在几周后为家庭聚会编写一个小图片拼图。

拼图应该是这样的:http://www.welt.de/spiele/online-spiele/article2128160/Bilderraetsel.html (只需按“Spiel starten”即可观看演示)

我知道我现在的解决方案非常缓慢且丑陋。但作为第一步,它正在发挥作用。

我根据图像的大小动态创建了许多矩形(这很重要,因为我将拼图用于不同的图像)。

然后,每隔 X 秒,一个矩形将变得不可见(不透明度步长变为 0)。

问题是,在应用程序中,矩形行之间有空格。

我尝试使用 StackPanel、WrapPanel 和 UniformGrid。使用 UniformGrid,我得到了最好的结果。

如果我会在内存中的整个图片大小上生成一个灰色图像,并在我的计时器中从这个内存图像中切掉一些矩形,那么最好的方法是。但我喜欢不透明效果,所以这是不可能的,不是吗?

这是我的 XAML:

<Window x:Class="PicturePuzzle.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow"
        Width="525"
        Height="420"
        Loaded="WindowLoaded">
  <Grid>
    <Grid Height="300" VerticalAlignment="Top">
      <Image x:Name="imgPicture"
             Source="/PicturePuzzle;component/Images/Koala.jpg"
             Stretch="Uniform" />
      <UniformGrid x:Name="ugMask"
                   Width="{Binding ElementName=imgPicture,
                                   Path=ActualWidth}"
                   Height="{Binding ElementName=imgPicture,
                                    Path=ActualHeight}" />

    </Grid>

    <StackPanel HorizontalAlignment="Center" VerticalAlignment="Bottom">
      <StackPanel Margin="0,0,0,10" Orientation="Horizontal">
        <Button x:Name="btnStart"
                Width="60"
                Margin="0,0,5,0"
                Click="BtnStartClick"
                Content="Start" />
        <Button x:Name="btnStop"
                Width="60"
                Click="BtnStopClick"
                Content="Stop"
                IsEnabled="False" />
        <Button x:Name="btnSolution"
                Margin="5,0,0,0"
                Click="BtnSolutionClick"
                Content="Lösung anzeigen" />
      </StackPanel>
      <Slider x:Name="slSpeed"
              IsDirectionReversed="True"
              Maximum="10"
              Minimum="1"
              ValueChanged="SlSpeedValueChanged"
              Value="3" />
    </StackPanel>
  </Grid>
</Window>

还有我的代码隐藏:

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace PicturePuzzle
{
  /// <summary>
  /// Interaction logic for MainWindow.xaml
  /// </summary>
  public partial class MainWindow
  {
    public MainWindow()
    {
      _rectangles = new List<Rectangle>();

      InitializeComponent();

      _timer = new DispatcherTimer();
      _generated = new List<int>();
      _random = new Random();
    }

    private readonly List<Rectangle> _rectangles;
    private readonly List<int> _generated;
    private readonly DispatcherTimer _timer;
    private readonly Random _random;

    private void WindowLoaded(object sender, RoutedEventArgs e)
    {
      var size = imgPicture.RenderSize;

      var columns = Convert.ToInt32(Math.Ceiling(size.Width/20));
      var rows = Convert.ToInt32(Math.Ceiling(size.Height/20));

      ugMask.Columns = columns;
      ugMask.Rows = rows;

      for (int y = 0; y < rows; y++)
      {
        for (int x = 0; x < columns; x++)
        {
          var rectangle = new Rectangle {Width = 20, Height = 20, Fill = Brushes.Gray};

          _rectangles.Add(rectangle);

          ugMask.Children.Add(rectangle);
        }
      }
    }

    private void BtnStartClick(object sender, RoutedEventArgs e)
    {
      btnStart.IsEnabled = false;
      btnStop.IsEnabled = true;

      _generated.Clear();
      _rectangles.ForEach(a => a.Opacity = 1);

      _timer.Interval = TimeSpan.FromSeconds(slSpeed.Value);
      _timer.Tick += TimerTick;
      _timer.Start();
    }

    private void TimerTick(object sender, EventArgs e)
    {
      if (_generated.Count >= _rectangles.Count)
      {
        _timer.Stop();
        return;
      }

      var random = GetNext();

      var alphaTimer = new DispatcherTimer {Interval = TimeSpan.FromSeconds(0.1)};

      alphaTimer.Tick += (o, args) =>
        {
          var rec = _rectangles[random];

          if (rec.Opacity <= 0)
          {
            alphaTimer.Stop();
            return;
          }

          rec.Opacity -= 0.1;
        };

      alphaTimer.Start();
    }

    private int GetNext()
    {
      int r;

      do
      {
        r = _random.Next(0, _rectangles.Count);
      } while (_generated.Contains(r));


      _generated.Add(r);

      return r;
    }

    private void BtnStopClick(object sender, RoutedEventArgs e)
    {
      btnStart.IsEnabled = true;
      btnStop.IsEnabled = false;

      _timer.Stop();
    }

    private void SlSpeedValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
    {
      if (_timer != null)
      {
        _timer.Interval = TimeSpan.FromSeconds((slSpeed.Value / 10));
      }
    }

    private void BtnSolutionClick(object sender, RoutedEventArgs e)
    {
      btnStop.IsEnabled = false;
      btnStart.IsEnabled = true;

      _timer.Stop();

      _rectangles.ForEach(a => a.Opacity = 0);
    }
  }
}

在这里你可以看到产生的结果:

欢迎任何提示!谢谢。

【问题讨论】:

    标签: c# wpf image grid


    【解决方案1】:

    我做了一些测试,你实际上有两个问题。

    首先,矩形被消除锯齿。 (这是 WPF 的默认设置。)您需要关闭矩形的抗锯齿功能以使边缘对齐。在创建矩形后添加以下行:

    rectangle.SetValue(RenderOptions.EdgeModeProperty, EdgeMode.Aliased);

    其次,如果 koala.jpg 的宽度在均匀拉伸到 300 的高度后,不是 20 的倍数,那么 20 x 20 的等距矩形之间就必须有间隙。结果中的差距是由于行被舍入并转换为 int32 时的舍入错误。

    你有两个选择:

    如果您不介意将图像压扁一点,可以将 Grid 元素的宽度设置为 20 的倍数。然后将 Image 标签的 Stretch 属性设置为“Fill”。这将使您的矩形保持正方形。

    您还可以将矩形的宽度设置为size.Width / columns 这会稍微拉伸它们以使其完全适合。为了更好地衡量,您还可以将它们的高度设置为size.Height / rows。因为size.Widthsize.Height 是浮点数,所以这个除法将纠正计算行和列时的舍入误差。这将允许任意大小的图像,但您的矩形不会完全是正方形。

    【讨论】:

    • 是的,这就是原因,但我怎样才能避免这个问题呢?我尝试将宽度和高度设置为 22,但这并没有改变任何东西。
    • 第二种方式会产生相同的结果,因为我计算了列:var columns = Convert.ToInt32(Math.Ceiling(size.Width/20));
    • 它不会给出相同的数字,因为当您四舍五入并转换为 int32 时,您的答案会丢失任何小数位。通过将宽度和高度除以列和行(使用浮点数学),您最终会计算此舍入误差。
    • 我试用了您的代码,发现导致问题的第二个问题。默认情况下,WPF 对所有内容进行抗锯齿处理,这会导致事物的边缘是半透明的。我用解决方案更新了我的答案。
    • 嘿,谢谢,我认为这就是解决方案。但我改变了生成面具的方式,我的新问题位于:stackoverflow.com/questions/13497896/…
    猜你喜欢
    • 1970-01-01
    • 2018-05-23
    • 2015-08-05
    • 2018-04-11
    • 2011-08-16
    • 1970-01-01
    • 2018-03-29
    • 2012-05-18
    • 2016-04-07
    相关资源
    最近更新 更多