【问题标题】:Placing an object randomly depending on window size根据窗口大小随机放置对象
【发布时间】:2016-04-01 17:13:39
【问题描述】:

我正在尝试根据窗口大小将对象放置在随机位置。 LayoutRoot 是它所在的网格的名称。

     //Give Dot a random position
     int left = random.Next(LayoutRoot.MinWidth, LayoutRoot.MaxWidth);
     int top = random.Next(-900, 900);
     Dot.Margin = new Thickness(left, top, 0, 0);

LayoutRoot.MinWidth 和 MaxWidth 错误:Cannot convert double to int

试过

    //Give Dot a random position
    double left = random.NextDouble(LayoutRoot.MinWidth, LayoutRoot.MaxWidth);
    double top = random.Next(-900, 900);
    Dot.Margin = new Thickness(left, top, 0, 0);

NextDouble 出错:Method NextDouble takes 2 arguments

【问题讨论】:

  • 您确定要使用Grid吗?如果你想在屏幕上随机放置一些东西,我想你会想使用Canvas。您可以使用 Canvas.SetX(x); Canvas.SetY(y); Canvas 控件用于此类事物,而 Grid 用于以整齐的行和列布局。

标签: c# wpf


【解决方案1】:

好的,把这个提高一点。修改了你的代码。此代码不假定任何预定义的高度或宽度,它根据LayoutRoot 的当前大小获取。它还抵消了Dot 的大小,因此它不会从屏幕上掉下来。

MainWindow.xaml

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication1"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid x:Name="LayoutRoot">
        <Ellipse Width="2" Height="2" Fill="Black" x:Name="Dot"></Ellipse>
    </Grid>
</Window>

MainWindow.xaml.cs

using System;
using System.Windows;

namespace WpfApplication1
{
    public partial class MainWindow
    {
        private static Random random = new Random();
        public MainWindow()
        {
            InitializeComponent();
            // Don't move dot until the window is loaded, not necessary but generally you don't want to hold up the window from displaying.
            this.Loaded += OnLoaded;
        }

        private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
        {
            // The farthest left the dot can be
            double minLeft = 0;
            // The farthest right the dot can be without it going off the screen
            double maxLeft = LayoutRoot.ActualWidth - Dot.Width;
            // The farthest up the dot can be
            double minTop = 0;
            // The farthest down the dot can be without it going off the screen
            double maxTop = LayoutRoot.ActualHeight - Dot.Height;


            double left = RandomBetween(minLeft, maxLeft);
            double top = RandomBetween(minTop, maxTop);
            Dot.Margin = new Thickness(left, top, 0, 0);
        }

        private double RandomBetween(double min, double max)
        {
            return random.NextDouble() * (max - min) + min;
        }
    }
}

【讨论】:

  • 没有错误,但是当我启动应用程序时找不到对象?
【解决方案2】:

这可能有效。

double mWidth = LayoutRoot.MinWidth;
double mxWidth = LayoutRoot.MaxWidth;
double left = random.NextDouble(mWidth, mxWidth);
double top = random.Next(-900, 900);
Dot.Margin = new Thickness(left, top, 0, 0);
}

【讨论】:

  • 再次收到错误Method NextDouble takes 2 arguments
【解决方案3】:

因此,在查看 Kelly 给出的答案后,我遇到了类似的问题,即加载后对象不会显示。我的目标是让应用程序的欢迎屏幕每 10 秒随机移动一次。因此,按照他的设计,出现了一个问题,即由于缺少列/行定义,网格没有实际长度,我们必须强制应用在每次尝试随机化时重新计算大小。

这是我使用的 XAML:

<Grid x:Name="LayoutRoot">
    <TextBlock x:Name="WelcomeTextBlock" 
               Height="200" 
               Style="{StaticResource WelcomeTextBlock}">
        Welcome!
    </TextBlock>
    <Ellipse Width="2" Height="2" x:Name="Dot"/>
</Grid>

更重要的是实际的代码隐藏:

public partial class WelcomePage : Page
    {
        private static Random Rnd = new Random();

        private static DispatcherTimer _timer;

        public WelcomePage()
        {
            InitializeComponent();
            this.Loaded += OnLoaded;
            this.Unloaded += OnClosing;
        }

        private void OnLoaded(object sender, RoutedEventArgs args)
        {
            this.LayoutRoot.Margin = GetNewMargin();
            _timer = new DispatcherTimer {Interval = TimeSpan.FromSeconds(5)};
            _timer.Tick += MoveWelcome;
            _timer.Start();
        }

        private void MoveWelcome(object sender, EventArgs e)
        {
            this.LayoutRoot.Margin = GetNewMargin();
        }

        private Thickness GetNewMargin()
        {
            this.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
            this.Arrange(new Rect(0, 0, this.DesiredSize.Width, this.DesiredSize.Height));
            var maxLeft = this.LayoutRoot.ActualWidth - Dot.Width;
            var maxTop = LayoutRoot.ActualHeight - Dot.Height;
            var left = RandomBetween(0, maxLeft);
            var top = RandomBetween(0, maxTop);
            return new Thickness(left, top, 0 ,0);
        }

        private static void OnClosing(object sender, RoutedEventArgs args)
        {
            _timer.Stop();
        }

        private static double RandomBetween(double min, double max) => Rnd.NextDouble() * (max - min) + max;

除了计时器功能之外,这里的主要变化是在计算边距厚度时,我们强制窗口,或者在我的情况下,页面更新屏幕的测量值并正确排列项目。

【讨论】:

    猜你喜欢
    • 2022-10-24
    • 1970-01-01
    • 1970-01-01
    • 2017-07-02
    • 1970-01-01
    • 1970-01-01
    • 2013-12-17
    • 2013-07-28
    • 2012-08-07
    相关资源
    最近更新 更多