我正在尝试使用包含一些垂直堆叠面板的表单,并且我尝试执行一些拖放操作,以便可以重新排序。到目前为止,除了我无法弄清楚的一个错误之外,它运作良好 前提是它是一个必须垂直堆叠的文件列表,但可以根据用户的需要重新排序,以形成我稍后生产的文档的页面列表。
尝试以下代码,您应该获得一个包含6个堆叠面板的表单。单击并向上或向下拖动其中任何一个,它们将重新排序。
问题是,如果您上下拖动 非常快 ,它们会开始相互重叠。
我已经将快捷键CTRL + B放在那里,以便在任何给定时间列出当前的面板顶部位置,并且当您不应该看到时,您会看到重复的数字。
问题在于MouseMove事件。我确定这种情况类似于竞争条件,字典无法跟上,或者索引的计算速度不够快,但我却摸不着头脑。我试过锁定它们但它没有帮助 我确信有更好的方法来实现这一点,所以我愿意接受建议,但考虑到这将永远不会超过30个面板,这符合我的需求。
为凌乱而道歉,我打算稍后整理一下!
public Form1()
{
InitializeComponent();
this.SuspendLayout();
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 601);
this.DoubleBuffered = true;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
this.MaximumSize = new System.Drawing.Size(300, 640);
this.MinimumSize = new System.Drawing.Size(300, 640);
this.Name = "Form1";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
this.ResumeLayout(false);
}
Dictionary<int, Panel> panelPositions = new Dictionary<int, Panel>();
static Random rnd = new Random();
int y;
int start;
static int index, previndex, currentindex, newindex, maxindex;
bool isDragging;
Panel currentPanel;
static readonly object Lock = new Object();
private void Form1_Load(object sender, EventArgs e)
{
Width = 300;
Height = 640;
int count = 5;
int currentTop = 0;
for (int i = 0; i <= count; i++)
{
Panel panel = new Panel();
panel.Width = 300;
panel.Height = 100;
panel.Top = currentTop;
panel.BackColor = RandomColor();
panel.Margin = Padding.Empty;
panel.Padding = Padding.Empty;
panel.BorderStyle = BorderStyle.None;
Label label = new Label();
label.Font = new Font("Segoe UI", 24.0f);
label.Text = (i + 1).ToString();
label.Top = 20;
label.Left = 20;
label.AutoSize = true;
panel.Controls.Add(label);
panel.MouseDown += new MouseEventHandler(MouseisDown);
panel.MouseMove += new MouseEventHandler(MouseMoves);
panel.MouseUp += new MouseEventHandler(MouseisUp);
lock (Lock)
{
panelPositions.Add(i, panel);
}
Controls.Add(panel);
currentTop += 100;
}
lock (Lock)
{
maxindex = panelPositions.Count - 1;
}
}
private void MouseisUp(object sender, MouseEventArgs e)
{
if (isDragging)
{
if (newindex < maxindex)
{
currentPanel.Top = newindex * 100;
}
else
{
currentPanel.Top = maxindex * 100;
}
}
isDragging = false;
}
// I'M SURE THE PROBLEM IS IN HERE SOMEWHERE.
private void MouseMoves(object sender, MouseEventArgs e)
{
// CHECK THE MOUSE IS STILL DOWN
if (isDragging)
{
// DRAG PANEL VERTICALLY WITH MOUSE
currentPanel.Location = new Point(currentPanel.Left, e.Y + currentPanel.Top - y);
// WORK OUT NEW INDEX POSITION
newindex = 0;
if ((currentPanel.Top + e.Y) > 0)
{
newindex = ((currentPanel.Top + e.Y) / 100);
}
// NEW POSITION?
if (currentindex != newindex)
{
// TRACK CHANGES
previndex = currentindex;
currentindex = newindex;
/* PRETTY SURE IT'S THIS BIT THAT'S WRONG */
// CHECK WE'RE NOT OUT OF BOUNDS
if (currentindex <= maxindex)
{
lock (Lock)
{
// RE-ARRANGE PANEL INDEX
panelPositions[previndex] = panelPositions[currentindex];
panelPositions[currentindex] = currentPanel;
panelPositions[previndex].Top = previndex * 100;
}
}
}
}
}
private void MouseisDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
currentPanel = sender as Panel;
isDragging = true;
currentPanel.BringToFront();
y = e.Y;
start = currentPanel.Top;
int i = 0;
if (currentPanel.Top > 0)
{
i = currentPanel.Top;
i = (i / 100);
}
index = i;
previndex = i;
currentindex = i;
}
else
{
isDragging = false;
}
}
private Color RandomColor()
{
Color randColor;
randColor = Color.FromArgb(RandomRGB(), RandomRGB(), RandomRGB());
return randColor;
}
private int RandomRGB()
{
return rnd.Next(1, 256);
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.B)
{
string message = string.Empty;
int count = panelPositions.Count;
for (int i = 0; i < count; i++)
{
message += @"Panel " + i.ToString() + @": " + panelPositions[i].Top.ToString() + Environment.NewLine;
}
MessageBox.Show(message);
}
}
谢谢!
编辑:我认为当面板超出表单的底部范围时,它会有所作为。如果您在表单中拖动,则问题不会发生。我认为这与之前的索引有关,但我无法看到它。
答案 0 :(得分:1)
更改
// NEW POSITION?
if (currentindex != newindex)
要
// NEW POSITION?
if (currentindex != newindex && newindex <= maxindex)
我想你知道为什么:)
P.s:你的&#34;编辑&#34;部分有点误导。