【问题标题】:Swiping images in C# Windows Forms app (Tinder swipe)在 C# Windows 窗体应用程序中滑动图像(Tinder 滑动)
【发布时间】:2021-09-24 05:30:56
【问题描述】:

我真的需要在我自己的应用程序中添加像约会应用程序(可能是 Tinder)那样滑动图像的可能性。如果图像向左滑动,则应为变量分配某个值(例如,+1)。如果向右,那么什么都不会改变(变量+0)。滑动图片后,下一张图片应该会平滑浮动(从前面,从底部,都没有关系)。

我尝试自己做,但不知道如何做。我知道在 Windows 窗体上比在 WPF 上更难做到这一点。我最近才开始对 WPF 感兴趣,所以在 WPF 上解决这个问题也会很有用,但 Windows 窗体仍然是一个优先事项。请帮我解决这个问题。

【问题讨论】:

    标签: c# wpf winforms tinder


    【解决方案1】:

    您忘记定义“滑动”。 Winforms 没有手指输入的概念,只有鼠标拖动的概念。

    您是否希望,如果操作员将鼠标向左拖动,图像也会随之移动?一个小的拖动就足够了,还是操作员应该将图像完全拖动到窗口之外?

    如果操作员拖动一小部分,但停止拖动,会发生什么情况?图像是否应该像没有阻力一样向后移动?还是应该将图像拖到一半?

    型号

    您使用了图像这个词,但实际上图像代表了更多的东西:在 Tinder 中,它代表图像背后的人、姓名、出生日期、描述和其他部分,其中包括图像。

    我们称之为Profile:每个配置文件都有多个属性,其中包括一个图像。

    class Profile
    {
        public Image Image {get; set;}
        ...
    }
    

    在您的模型中,您将需要一个“要显示的配置文件”的 FIFO 序列、一组被拒绝的配置文件和一组接受的配置文件。你没有说你想对被拒绝和接受的配置文件做什么,所以我所做的只是将被拒绝的配置文件放在一个存储库中,将接受的配置文件放在不同的存储库中。

    存储库中发生的事情对于模型是隐藏的。可能是您删除了所有内容,或者将其保存在文件、数据库或其他任何东西中,您的模型不必知道。它只需要知道两个存储库都需要有一个接口来放入配置文件:

    interface IProfileRepository
    {
        void Add (Profile profile);
    }
    

    包含被拒绝图像的存储库可能会直接丢弃个人资料,而其他存储库可能会执行诸如通知个人资料所有者他已被接受的事情。

    我们还需要一些输入配置文件。我也不知道他们来自哪里:

    interface IProfileSource
    {
        Profile GetProfile(); // returns the next Profile
    }
    

    实际的 ProfileSource 可能会从 XML 文件、互联网或其他任何地方读取数据,这不在问题范围内。

    所以在您的程序中,您将拥有以下内容:

    class ProfileModel
    {
    
        private IProfileSource ProfileSource {get;} = new ...;
        private IProfileRepository AcceptedProfiles {get;} = new ...;
        private IProfileRepository RejectedProfiles {get;} = new ...;
    
        public Profile GetNextProfile()
        {
            return ProfileSource.GetProfile();
        }
    
        public void AcceptProfile(Profile profile)
        {
            AcceptedProfiles.Add(profile);
        }
    
        public void RejectProfile(Profile profile)
        {
            RejectedProfiles.Add(profile);
        }
    

    查看

    显示配置文件图像的表单需要一个显示配置文件的用户控件。它隐藏了配置文件的显示内容。您可能只会显示图像,但如果需要,您可以让它显示人的年龄,或姓名、位置等。您的程序所知道的就是您可以要求 ProfileControl 显示一个配置文件,什么是否显示以及如何显示取决于 ProfileControl。

    使用 Visual Studio 创建一个名为 ProfileControl 的新 UserControl。使用 Visual Studio 设计器在需要显示配置文件时在控件上绘制要显示的内容。如果您只想显示图像,请将 PictureBox 添加到 ProfileControl 并让它停靠。如果您还想显示名称,请添加标签等

    class ProfileControl : UserControl
    {
        private Profile profile;
    
        public ProfileControl()
        {
            InitializeComponents();
        }
    
        public Profile Profile
        {
            get => this.profile;
            set
            {
                if (this.Profile != value)
                {
                    this.profile = value;
                    this.pictureBox1.Image = this.profile.Image;
                }
            }
        }
    }
    

    考虑添加一个事件 ProfileChanged 和一个受保护的方法 OnProfileChanged,以通知其他人此 ProfileControl 显示一个新图像。

    您将需要另一个 UserControl 来执行 ProfileControl 的拖动。它将有两个 ProfileControl:当前一个和下一个。在 MouseDrag 时,当前 ProfileControl 的位置和下一个 ProfileControl 将改变。下一个 ProfileControl 将与当前的 ProfileControl 相邻,具体取决于拖动的方向。

    这个SwipeControl 隐藏了滑动是如何完成的。 SwipeControl(= 软件,而不是操作员)的用户只会设置当前和下一个配置文件,并且只要当前配置文件通过事件被接受或拒绝,它就会收到通知。该事件将自动设置下一个配置文件(如果有)

    使用 Visual Studio 设计器为 SwipeControl 提供两个 ProfileControl。为事件添加事件处理程序:

    • MouseDown:记住当前鼠标位置为DragStartPosition。为 CurrentProfileControl 和 NextProfileControl 指定 SwipeControl 的 ClientArea 的大小。将 CurrentProfileControl 的 Location 设置为 (0, 0),因此它位于 SwipeControl 的 ClientArea 的左上角。 NextProfileControl 仍然不可见,我们不知道操作员是向左滑动还是向右滑动。
    • MouseMove:鼠标移动的水平距离 = 当前鼠标位置 X - DragStartPosition X。使用此移动距离移动 X 位置 CurrentProfileControl。决定 NextProfileControl 应该位于 CurrentProfileControl 的左侧还是右侧。计算位置。使 NextProfileControl 可见。
    • MouseUp:如果距离已超过某个最小值,则将滑动设置为完成,否则撤消:停靠当前并使下一个不可见。

    SwipeComplete:如果接受则引发事件 ProfileAccepted,如果拒绝则引发事件 ProfileRejected。 NextProfileControl 中的 Profile 设置为 CurrentProfileControl。获取 NextProfile 并将其放入 NextProfileControl

    class SwipeControl : CustomControl
    {
    
        public Profile CurrentProfile
        {
            get => this.CurrentProfileControl.Profile;
            set => this.CurrentProfileControl.Profile = value;
        }
    
        public Profile NextProfile
        {
            get => this.NextProfileControl.Profile;
            set => this.NextProfileControl.Profile = value;
        }
    
        public event EventHandler ProfileAccepted;
        public event EventHandler ProfileRejected;
    
        protected virtual void OnProfileAccepted()
        {
            // raise event ProfileAccepted
            this.ProfileAccepted?.Invoke(this, EventArgs.Empty);
        }
    

    使用 Visual Studio Designer 添加事件处理程序并按照编写的代码实现。

    ##SwipeForm##

    使用 Visual Studio 设计器将 SwipeControl 添加到 SwipeForm。同时添加模型。

    订阅 SwipeControl 的 Accepted / Rejected 事件。

    加载表单时:从模型中获取第一个和下一个 Profile 并将它们放入 SwipeControl

    事件 ProfileAccepted 时:从 SwipeControl 获取 CurrentProfile 并将其作为 Accepted 放入模型中。 nextProfile 将是当前的。从模型中获取下一个并将其设置为 SwipeControl 中的下一个配置文件。

    对事件 ProfileRejected 做类似的事情

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-19
      • 1970-01-01
      • 1970-01-01
      • 2015-02-21
      • 2015-05-30
      • 1970-01-01
      相关资源
      最近更新 更多